function tablefield_field_formatter_view in TableField 7.3
Same name and namespace in other branches
- 7 tablefield.module \tablefield_field_formatter_view()
- 7.2 tablefield.module \tablefield_field_formatter_view()
Implements hook_field_formatter_view().
File
- ./
tablefield.module, line 869 - Provides a set of fields that can be used to store tabular data with a node.
Code
function tablefield_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
$settings = $display['settings'];
$formatter = $display['type'];
if (!empty($items)) {
switch ($display['type']) {
case 'format_raw':
$values = array();
foreach ($items as $delta => $table) {
$value = unserialize($table['value']);
// Swap rows and columns if the header is vertical (first column).
if ($settings['vertheader']) {
$transposed = tablefield_transpose($value['tabledata']);
unset($value['tabledata']);
array_pop($transposed);
// Swap column and row key names.
foreach ($transposed as $colk => $colv) {
foreach ($colv as $rowk => $rowv) {
$value['tabledata'][str_replace('col_', 'row_', $colk)][str_replace('row_', 'col_', $rowk)] = $rowv;
}
// Add a 'weight' although the value is not relevant.
$value['tabledata'][str_replace('col_', 'row_', $colk)]['weight'] = 0;
}
}
// Remove unneeded data.
unset($value['rebuild']);
unset($value['import']);
unset($value['paste']);
// DEVELOPERS! Extra future data should be captured and unset below.
$caption = $value['caption'];
unset($value['caption']);
if ($settings['usearraykeys'] === 'Header' || $settings['usearraykeys'] === 'Both') {
// Keep first row values (header) to use for array keys later.
$keys = $value['tabledata']['row_0'];
// Remove linebreaks from array keys.
array_walk_recursive($keys, function (&$key) {
$key = str_replace(array(
"\r",
"\n",
"<br />",
), '', $key);
});
// If a header value is empty use the column key (col_#).
foreach ($keys as $key => $content) {
if (empty($content)) {
$keys[$key] = $key;
}
}
// Warning about columns with duplicate names being suppressed.
$unique = array_unique($keys);
$duplicates = array_diff_assoc($keys, $unique);
foreach ($duplicates as $duplicate) {
drupal_set_message(t('The column header "%key" appears multiple times in a table. In the JSON output only the last column with this key is used to avoid duplicate names.', array(
'%key' => $duplicate,
)), 'warning', FALSE);
}
unset($keys['weight']);
// Remove the first row (header).
unset($value['tabledata']['row_0']);
if ($settings['usearraykeys'] === 'Both') {
// Remove the first column from the keys.
unset($keys['col_0']);
// Make number of elements same as $row for array_combine later.
unset($keys['weight']);
}
}
foreach ($value['tabledata'] as $key => $row) {
unset($row['weight']);
if ($settings['usearraykeys'] === 'Header' || $settings['usearraykeys'] === 'Both') {
if ($settings['usearraykeys'] === 'Both') {
$row_ident = $row['col_0'];
// Clean up unneeded data.
unset($value['tabledata'][$key]);
unset($row['col_0']);
$row = array_combine($keys, $row);
// If the first column value is empty use the row key (row_#).
$row_id = empty($row_ident) ? $key : $row_ident;
$row_id = str_replace(array(
"\r",
"\n",
"<br />",
), '', $row_id);
// Warning about rows with duplicate names being suppressed.
if (isset($value['tabledata'][$row_id])) {
drupal_set_message(t('The row header "%row_id" appears multiple times in a table. In the JSON output only the last row with this key is used to avoid duplicate names.', array(
'%row_id' => $row_id,
)), 'warning', FALSE);
}
$value['tabledata'][$row_id] = $row;
// Remove the old key from the data set if it was replaced.
if (!empty($row_ident)) {
unset($value['tabledata'][$key]);
}
}
$unique = array_unique($keys);
$row = array_combine($unique, $row);
}
if ($settings['usearraykeys'] != 'Both') {
$value['tabledata'][$key] = $row;
}
}
// For a row identifier key to be retained we need to insert a
// numeric index key for each row.
if ($settings['usearraykeys'] === 'Both' || $settings['rowkey']) {
$i = 0;
foreach ($value as $key => $val) {
$value[$i][$key] = $val;
// Remove original key. We'll get it back with array_values().
unset($value[$key]);
$i++;
}
}
if ($settings['tabledataonly']) {
$value = reset($value);
}
else {
// DEVELOPERS! Extra future data should be unset below (e.g. title).
$value['caption'] = $caption;
}
// Use the set wrapper for the table data.
if (isset($value[0]['tabledata']) && $settings['tabledatakey'] !== 'tabledata') {
$value[0][$settings['tabledatakey']] = $value[0]['tabledata'];
unset($value[0]['tabledata']);
}
elseif (isset($value['tabledata']) && $settings['tabledatakey'] !== 'tabledata') {
$value[$settings['tabledatakey']] = $value['tabledata'];
unset($value['tabledata']);
}
// Add the table to the final output.
if ($settings['tabledataonly']) {
array_push($values, array_values($value));
}
else {
$value[$settings['tabledatakey']] = $settings['usearraykeys'] === 'Both' || $settings['rowkey'] ? $value[0][$settings['tabledatakey']] : array_values($value[$settings['tabledatakey']]);
unset($value[0]);
krsort($value);
array_push($values, $value);
}
// If the field is not plain text and a text area then remove
// linebreaks.
$format = isset($items[$delta]['format']) ? $items[$delta]['format'] : 'plain_text';
array_walk_recursive($values, function (&$value) use ($format, $settings) {
if ($format !== 'plain_text') {
if ($settings['xml']) {
switch ($settings['xml_safe']) {
case 'htmlspecialchars':
$value = str_replace(array(
"\r",
"\n",
), '', htmlspecialchars($value));
break;
case 'cdata':
if (preg_match('/[&"\'<>]/', $value)) {
$value = str_replace(array(
"\r",
"\n",
), '', '<![CDATA[' . str_replace(']]>', '', $value) . ']]>');
}
else {
$value = str_replace(array(
"\r",
"\n",
), '', $value);
}
break;
default:
$value = str_replace(array(
"\r",
"\n",
), '', '<![CDATA[' . str_replace(']]>', '', $value) . ']]>');
break;
}
}
else {
$value = str_replace(array(
"\r",
"\n",
), '', $value);
}
}
});
}
// Serve pretty print with a fixed-width font and preserve spaces and
// line breaks.
// Show pretty print on node pages and raw on other pages.
$prettyprint = menu_get_object() && arg(2) !== 'themeless' ? JSON_PRETTY_PRINT : FALSE;
if ($prettyprint) {
$element['#prefix'] = '<pre>';
$element['#suffix'] = '</pre>';
}
$numeric_check = $settings['numeric_check'] ? JSON_NUMERIC_CHECK : FALSE;
// Avoid a wrapping array if we have a single table (not multi-value).
if (!(count($values) - 1)) {
$values = array_shift($values);
}
// Render multiple values as one to ensure valid JSON (e.g. seperator)
// or XML.
if ($settings['xml']) {
// Creating object of SimpleXMLElement.
$xml_data = new SimpleXMLElement('<?xml version="1.0"?><' . $settings['tabledatakey'] . '></' . $settings['tabledatakey'] . '>');
// Flatten the array if we only have one element.
if (count($values) === 1) {
$values = current($values);
}
// Function call to convert array to xml.
array_to_xml($values, $xml_data);
if ($prettyprint) {
$dom = dom_import_simplexml($xml_data)->ownerDocument;
$dom->formatOutput = TRUE;
$output = $dom
->saveXML();
$markup = '<xmp>' . $output . '</xmp>';
// Let other modules change the output.
$context = array(
'entity_type' => $entity_type,
'entity' => $entity,
'field' => $field,
'instance' => $instance,
'language' => $langcode,
'items' => $items,
'display' => $display,
'table_field_output_type' => 'xml_pretty_print',
);
drupal_alter('tablefield_output', $markup, $context);
$element[0] = array(
'#markup' => $markup,
);
}
else {
$output = $xml_data
->asXML();
$markup = str_replace('<?xml version="1.0"?>', '', $output);
// Let other modules change the output.
$context = array(
'entity_type' => $entity_type,
'entity' => $entity,
'field' => $field,
'instance' => $instance,
'language' => $langcode,
'items' => $items,
'display' => $display,
'table_field_output_type' => 'xml_raw',
);
drupal_alter('tablefield_output', $markup, $context);
$element[0] = array(
'#markup' => $markup,
);
}
}
else {
$markup = json_encode($values, $prettyprint | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | $numeric_check);
// Let other modules change the output.
$context = array(
'entity_type' => $entity_type,
'entity' => $entity,
'field' => $field,
'instance' => $instance,
'language' => $langcode,
'items' => $items,
'display' => $display,
'table_field_output_type' => $prettyprint ? 'json_pretty_print' : 'json_raw',
);
drupal_alter('tablefield_output', $markup, $context);
$element[0] = array(
// See http://php.net/manual/en/json.constants.php#119565.
'#markup' => check_plain($markup),
);
}
break;
default:
foreach ($items as $delta => $table) {
// Check for table caption.
$raw = unserialize($table['value']);
$caption = isset($raw['caption']) ? check_plain($raw['caption']) : '';
// Rationalize the stored data.
if (!empty($table['tablefield'])) {
$tabledata = $table['tablefield'];
}
elseif (!empty($table['value'])) {
$tabledata = unserialize($table['value']);
}
// Run the table through input filters.
if (isset($tabledata['tabledata'])) {
if (!empty($tabledata['tabledata'])) {
if ($settings['trim_trailing_rows']) {
$tabledata['tabledata'] = tablefield_trim($tabledata['tabledata']);
}
if ($settings['trim_trailing_cols']) {
$tabledata['tabledata'] = tablefield_rtrim_cols($tabledata['tabledata']);
}
if ($settings['hide_empty_rows']) {
$tabledata['tabledata'] = tablefield_hide_rows($tabledata['tabledata']);
}
if ($settings['hide_empty_cols']) {
$tabledata['tabledata'] = tablefield_hide_cols($tabledata['tabledata']);
}
if ($settings['hide_cols_skip_head']) {
$tabledata['tabledata'] = tablefield_hide_cols($tabledata['tabledata'], TRUE);
}
foreach ($tabledata['tabledata'] as $row_key => $row) {
foreach ($row as $col_key => $cell) {
if (!empty($table['format']) && $col_key !== 'weight') {
$tabledata[$row_key][$col_key] = array(
'data' => check_markup($cell, $table['format']),
'class' => array(
$row_key,
$col_key,
),
);
}
elseif ($col_key !== 'weight') {
$tabledata[$row_key][$col_key] = array(
'data' => check_plain($cell),
'class' => array(
$row_key,
$col_key,
),
);
}
}
}
}
// Grab the header orientation.
$header_orientation = !empty($tabledata['rebuild']['header_orientation']) ? $tabledata['rebuild']['header_orientation'] : (isset($instance['default_value'][0]['tablefield']['rebuild']['header_orientation']) ? $instance['default_value'][0]['tablefield']['rebuild']['header_orientation'] : 'Horizontal');
// Pull the header for theming.
unset($tabledata['caption']);
unset($tabledata['tabledata']);
unset($tabledata['rebuild']);
unset($tabledata['import']);
unset($tabledata['paste']);
$header_data = isset($tabledata['row_0']) ? $tabledata['row_0'] : NULL;
// Check for an empty header, if so we don't want to theme it.
$noheader = TRUE;
if (empty($settings['hide_header']) && $header_data) {
foreach ($header_data as $cell) {
if (strlen($cell['data']) > 0) {
$noheader = FALSE;
break;
}
}
}
$header = $noheader ? [] : $header_data;
$entity_info = entity_get_info($entity_type);
$entity_id = !empty($entity_info['entity keys']['id']) ? $entity->{$entity_info['entity keys']['id']} : NULL;
// Remove the first row from the tabledata.
if (empty($settings['hide_header']) && $header_data || $settings['hide_header']) {
array_shift($tabledata);
}
// Theme the table for display, but only if we have printable
// table data.
if (!$settings['hide_cols_skip_head'] || $tabledata || $header) {
$element[$delta] = array(
'#theme' => 'tablefield_view',
'#caption' => $caption,
'#header_orientation' => $header_orientation,
'#sticky' => isset($settings['sticky_header']) ? $settings['sticky_header'] : NULL,
'#striping' => isset($settings['striping']) ? $settings['striping'] : NULL,
'#sortable' => isset($settings['sortable']) ? $settings['sortable'] : NULL,
'#header' => $header,
'#rows' => $tabledata,
'#delta' => $delta,
'#table_custom_class_attributes' => !trim($settings['table_custom_class_attributes']) == FALSE ? $settings['table_custom_class_attributes'] : NULL,
'#export' => isset($settings['export_csv']) ? $settings['export_csv'] : NULL,
'#entity_type' => $entity_type,
'#entity_id' => $entity_id,
'#field_name' => $field['field_name'],
'#langcode' => $langcode,
'#formatter' => $formatter,
);
}
}
}
}
}
return $element;
}