field_group_table.module

Adds a "Table" format to Field Groups.

Functions

Namesort descending Description
field_group_table_ctools_plugin_api Implements hook_ctools_plugin_api().
field_group_table_field_group_formatter_info Implements hook_field_group_formatter_info().
field_group_table_field_group_format_settings Implements hook_field_group_format_settings().
field_group_table_field_group_pre_render Implements hook_field_group_pre_render().
field_group_table_theme Implements hook_theme().
theme_field_group_table_wrapper Returns HTML for a field_group_table_wrapper.
_field_group_table_row_build Builds a table row for rendering.

Constants

File

field_group_table.module
View source
  1. <?php
  2. /**
  3. * @file
  4. * Adds a "Table" format to Field Groups.
  5. */
  6. define('FIELD_GROUP_TABLE_LABEL_HIDDEN', 1);
  7. define('FIELD_GROUP_TABLE_LABEL_ABOVE', 2);
  8. define('FIELD_GROUP_TABLE_LABEL_CAPTION', 3);
  9. define('FIELD_GROUP_TABLE_EMPTY_LABEL_KEEP', 1);
  10. define('FIELD_GROUP_TABLE_EMPTY_LABEL_MERGE', 2);
  11. /**
  12. * Implements hook_ctools_plugin_api().
  13. */
  14. function field_group_table_ctools_plugin_api($owner, $api) {
  15. if ($owner == 'field_group' && $api == 'field_group') {
  16. return array('version' => 1);
  17. }
  18. }
  19. /**
  20. * Implements hook_theme().
  21. */
  22. function field_group_table_theme() {
  23. return array(
  24. 'field_group_table_wrapper' => array(
  25. 'render element' => 'element',
  26. ),
  27. );
  28. }
  29. /**
  30. * Implements hook_field_group_formatter_info().
  31. */
  32. function field_group_table_field_group_formatter_info() {
  33. return array(
  34. 'display' => array(
  35. 'table' => array(
  36. 'label' => t('Table'),
  37. 'description' => t('This fieldgroup renders fields in a 2-column table with the label in the left column, and the value in the right column.'),
  38. 'instance_settings' => array(
  39. 'label_visibility' => FIELD_GROUP_TABLE_LABEL_CAPTION,
  40. 'desc' => '',
  41. 'first_column' => '',
  42. 'second_column' => '',
  43. 'empty_label_behavior' => FIELD_GROUP_TABLE_EMPTY_LABEL_KEEP,
  44. 'table_row_striping' => FALSE,
  45. 'always_show_field_label' => FALSE,
  46. 'classes' => '',
  47. ),
  48. ),
  49. ),
  50. 'form' => array(
  51. 'table' => array(
  52. 'label' => t('Table'),
  53. 'description' => t('This fieldgroup renders fields in a 2-column table with the label in the left column, and the value in the right column.'),
  54. 'instance_settings' => array(
  55. 'label_visibility' => FIELD_GROUP_TABLE_LABEL_CAPTION,
  56. 'desc' => '',
  57. 'first_column' => '',
  58. 'second_column' => '',
  59. 'empty_label_behavior' => FIELD_GROUP_TABLE_EMPTY_LABEL_KEEP,
  60. 'table_row_striping' => FALSE,
  61. 'always_show_field_label' => FALSE,
  62. 'classes' => '',
  63. ),
  64. ),
  65. ),
  66. );
  67. }
  68. /**
  69. * Implements hook_field_group_format_settings().
  70. */
  71. function field_group_table_field_group_format_settings($group) {
  72. // Add a wrapper for extra settings to use by others.
  73. $form = array(
  74. 'instance_settings' => array(
  75. '#tree' => TRUE,
  76. '#weight' => 2,
  77. ),
  78. );
  79. $field_group_types = field_group_formatter_info();
  80. $mode = $group->mode == 'form' ? 'form' : 'display';
  81. $formatter = $field_group_types[$mode][$group->format_type];
  82. $settings = $group->format_settings['instance_settings'];
  83. // Add optional instance_settings.
  84. switch ($group->format_type) {
  85. case 'table':
  86. $form['instance_settings']['label_visibility'] = array(
  87. '#title' => t('Label visibility'),
  88. '#description' => t('This option determines how to display the Field group label and description.'),
  89. '#type' => 'select',
  90. '#options' => array(
  91. FIELD_GROUP_TABLE_LABEL_HIDDEN => t('Hidden'),
  92. FIELD_GROUP_TABLE_LABEL_ABOVE => t('Above table'),
  93. FIELD_GROUP_TABLE_LABEL_CAPTION => t('Table caption'),
  94. ),
  95. '#default_value' => isset($settings['label_visibility']) ? $settings['label_visibility'] : $formatter['instance_settings']['label_visibility'],
  96. );
  97. $form['instance_settings']['desc'] = array(
  98. '#title' => t('Description for the group.'),
  99. '#type' => 'textarea',
  100. '#default_value' => isset($settings['desc']) ? $settings['desc'] : $formatter['instance_settings']['desc'],
  101. );
  102. $form['instance_settings']['first_column'] = array(
  103. '#title' => t('First column header'),
  104. '#description' => t('Use this field to add a table header.'),
  105. '#type' => 'textfield',
  106. '#default_value' => isset($settings['first_column']) ? $settings['first_column'] : $formatter['instance_settings']['first_column'],
  107. );
  108. $form['instance_settings']['second_column'] = array(
  109. '#title' => t('Second column header'),
  110. '#description' => t('Use this field to add a table header.'),
  111. '#type' => 'textfield',
  112. '#default_value' => isset($settings['second_column']) ? $settings['second_column'] : $formatter['instance_settings']['second_column'],
  113. );
  114. $form['instance_settings']['empty_label_behavior'] = array(
  115. '#title' => t('Empty label behavior'),
  116. '#type' => 'select',
  117. '#options' => array(
  118. FIELD_GROUP_TABLE_EMPTY_LABEL_KEEP => t('Keep empty label cell'),
  119. FIELD_GROUP_TABLE_EMPTY_LABEL_MERGE => t('Merge cells')
  120. ),
  121. '#default_value' => isset($settings['empty_label_behavior']) ? $settings['empty_label_behavior'] : $formatter['instance_settings']['empty_label_behavior'],
  122. );
  123. $form['instance_settings']['table_row_striping'] = array(
  124. '#title' => t('Table row striping'),
  125. '#description' => t('Adds zebra striping on the table rows.'),
  126. '#type' => 'checkbox',
  127. '#default_value' => isset($settings['table_row_striping']) ? $settings['table_row_striping'] : $formatter['instance_settings']['table_row_striping'],
  128. );
  129. $form['instance_settings']['always_show_field_label'] = array(
  130. '#title' => t('Always show field label'),
  131. '#description' => t('Forces the field label to always display in the first column and renders the field normally.'),
  132. '#type' => 'checkbox',
  133. '#default_value' => isset($settings['always_show_field_label']) ? $settings['always_show_field_label'] : $formatter['instance_settings']['always_show_field_label'],
  134. );
  135. break;
  136. }
  137. return $form;
  138. }
  139. /**
  140. * Implements hook_field_group_pre_render().
  141. */
  142. function field_group_table_field_group_pre_render(&$element, $group, &$form) {
  143. // We only process the 'table' group type.
  144. if ($group->format_type != 'table') {
  145. return;
  146. }
  147. $view_mode = isset($form['#view_mode']) ? $form['#view_mode'] : 'form';
  148. $mode = $group->mode == 'form' ? 'form' : 'display';
  149. $settings = $group->format_settings['instance_settings'];
  150. $label = check_plain($group->label);
  151. // Build the caption and description of this group.
  152. $caption = array();
  153. if ($settings['label_visibility'] == FIELD_GROUP_TABLE_LABEL_ABOVE) {
  154. $caption = array(
  155. '#type' => 'item',
  156. '#title' => $label,
  157. '#description' => field_filter_xss($settings['desc']),
  158. );
  159. }
  160. // Build the table header if necessary.
  161. $header = array();
  162. if ($settings['first_column'] || $settings['second_column']) {
  163. $header = array(
  164. check_plain($settings['first_column']),
  165. check_plain($settings['second_column']),
  166. );
  167. }
  168. // Create the element.
  169. $element += array(
  170. '#theme' => 'field_group_table_wrapper',
  171. '#title' => $group->label,
  172. '#mode' => $mode,
  173. '#groups' => array_keys($form['#groups']),
  174. '#settings' => $settings,
  175. '#attributes' => array(
  176. 'class' => array_merge(array('field-group-table', $group->group_name), explode(' ', $settings['classes'])),
  177. ),
  178. '#caption' => $caption,
  179. // We will add the table rows upon rendering, as doing it here means
  180. // messing up the field group hierarchy, which causes issues.
  181. '#field_group_table' => array(
  182. '#theme' => "table__field_group_table__$group->group_name",
  183. '#header' => $header,
  184. '#caption' => ($settings['label_visibility'] == FIELD_GROUP_TABLE_LABEL_CAPTION) ? $label : NULL,
  185. '#attributes' => array(
  186. 'class' => array('field-group-format', $group->group_name),
  187. ),
  188. ),
  189. );
  190. }
  191. /**
  192. * Returns HTML for a field_group_table_wrapper.
  193. */
  194. function theme_field_group_table_wrapper($variables) {
  195. $element = $variables['element'];
  196. $mode = $element['#mode'];
  197. $groups = $element['#groups'];
  198. $settings = $element['#settings'];
  199. // Build the table rows.
  200. $rows = array();
  201. foreach (element_children($element, TRUE) as $child) {
  202. // In some cases a child may be completely empty and therefore will be
  203. // useless to us, because it will render as an empty table row. See
  204. // http://drupal.org/node/1985606 for example.
  205. if ($mode == 'display' && !in_array($child, $groups) && !isset($element[$child]['#theme']) && !isset($element[$child]['#markup']) && !isset($element[$child]['#prefix']) && !isset($element[$child]['#suffix'])) {
  206. unset($element[$child]);
  207. continue;
  208. }
  209. $variables = array(
  210. 'element' => $element[$child],
  211. 'settings' => $settings,
  212. 'mode' => $mode,
  213. );
  214. unset($element[$child]);
  215. $rows[] = _field_group_table_row_build($variables);
  216. }
  217. $element['#field_group_table']['#rows'] = $rows;
  218. $output = '<div id="' . $element['#id'] . '"' . drupal_attributes($element['#attributes']) . ">\n";
  219. $output .= drupal_render($element['#caption']) . "\n";
  220. $output .= drupal_render($element['#field_group_table']) . "\n";
  221. $output .= "</div>\n";
  222. return $output;
  223. }
  224. /**
  225. * Builds a table row for rendering.
  226. */
  227. function _field_group_table_row_build($variables) {
  228. // Merge defaults.
  229. $variables += array(
  230. 'row_class' => array(),
  231. 'content_attributes' => array(),
  232. );
  233. $row = array(
  234. 'data' => array(),
  235. 'no_striping' => !$variables['settings']['table_row_striping'],
  236. 'class' => $variables['row_class'],
  237. );
  238. switch ($variables['mode']) {
  239. case 'display':
  240. // In some cases (like with field extra fields) #title and #label_display
  241. // may not be set. In that case we try to use #label as the title instead,
  242. // as that is commonly used.
  243. $title = '';
  244. if (isset($variables['element']['#title'])) {
  245. $title = $variables['element']['#title'];
  246. }
  247. elseif (isset($variables['element']['#label'])) {
  248. $title = $variables['element']['#label'];
  249. }
  250. $label_display = isset($variables['element']['#label_display']) ? isset($variables['element']['#label_display']) : 'above';
  251. // Display the label in the first column, if 'always show field label' is
  252. // set.
  253. if ($variables['settings']['always_show_field_label']) {
  254. $row['data'][] = array(
  255. 'data' => $title,
  256. 'header' => TRUE,
  257. 'class' => array('field-label'),
  258. );
  259. }
  260. // Display the label in the first column, if it's set to "above" and the
  261. // title isn't empty.
  262. elseif ($label_display == 'above' && $title != '') {
  263. $row['data'][] = array(
  264. 'data' => $title,
  265. 'header' => TRUE,
  266. 'class' => array('field-label'),
  267. );
  268. // Do not display the label in the second column.
  269. $variables['element']['#label_display'] = 'hidden';
  270. }
  271. // Display an empty cell if we won't display the title and 'empty label
  272. // behavior' is set to keep empty label cells.
  273. elseif ($variables['settings']['empty_label_behavior'] == FIELD_GROUP_TABLE_EMPTY_LABEL_KEEP) {
  274. $row['data'][] = array(
  275. 'data' => '&nbsp;',
  276. 'header' => TRUE,
  277. 'class' => array('field-label', 'field-label-hidden'),
  278. );
  279. }
  280. // Otherwise we merge the cells.
  281. else {
  282. $variables['content_attributes']['colspan'] = 2;
  283. }
  284. break;
  285. case 'form':
  286. $class = array('field-label');
  287. // Attempt to find a title we can use.
  288. $title = '';
  289. if (isset($variables['element']['#title'])) {
  290. $title = $variables['element']['#title'];
  291. $required = $variables['element']['#required'];
  292. $variables['element']['#title'] = '';
  293. $variables['element']['#required'] = FALSE;
  294. }
  295. elseif (isset($variables['element']['#language']) && isset($variables['element'][$variables['element']['#language']]['#title'])) {
  296. $title = $variables['element'][$variables['element']['#language']]['#title'];
  297. $required = $variables['element'][$variables['element']['#language']]['#required'];
  298. $variables['element'][$variables['element']['#language']]['#title'] = '';
  299. $variables['element'][$variables['element']['#language']]['#required'] = FALSE;
  300. }
  301. elseif (isset($variables['element']['#language']) && isset($variables['element'][$variables['element']['#language']][0]['#title'])) {
  302. $title = $variables['element'][$variables['element']['#language']][0]['#title'];
  303. $required = $variables['element'][$variables['element']['#language']][0]['#required'];
  304. $variables['element'][$variables['element']['#language']][0]['#title'] = '';
  305. $variables['element'][$variables['element']['#language']][0]['#required'] = FALSE;
  306. }
  307. if ($title != '' || ($title == '' && $variables['settings']['empty_label_behavior'] == FIELD_GROUP_TABLE_EMPTY_LABEL_KEEP)) {
  308. $row['data'][] = array(
  309. 'data' => ($title == '') ? '&nbsp;' : array(
  310. '#type' => 'item',
  311. '#title' => $title,
  312. '#required' => $required,
  313. ),
  314. 'header' => TRUE,
  315. 'class' => $class,
  316. );
  317. }
  318. else {
  319. $variables['content_attributes']['colspan'] = 2;
  320. }
  321. break;
  322. }
  323. // Add the field's content.
  324. $row['data'][] = $variables['content_attributes'] + array(
  325. 'data' => $variables['element'],
  326. 'class' => array('field-content'),
  327. );
  328. return $row;
  329. }