function tablefield_field_widget_form in TableField 7.3
Same name and namespace in other branches
- 7 tablefield.module \tablefield_field_widget_form()
- 7.2 tablefield.module \tablefield_field_widget_form()
Implements hook_field_widget_form().
File
- ./
tablefield.module, line 1248 - Provides a set of fields that can be used to store tabular data with a node.
Code
function tablefield_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
$form['#after_build'][] = 'tablefield_after_build';
$settings = isset($instance['display']['default']['settings']) ? $instance['display']['default']['settings'] : FALSE;
$element['#type'] = 'tablefield';
$form['#attributes']['enctype'] = 'multipart/form-data';
if ($settings) {
$hide_header = isset($settings['hide_header']) ? $settings['hide_header'] : FALSE;
}
/* Tablefield is sometimes embedded within another form by other modules, such
* as Field Collection. Because of that, we cannot rely on field_name and
* $delta to provide a unique ID for this element. Instead we use a
* concatenation of the field parents along with the current field name,
* language, delta and tablefield key.
*/
$tablefield_parents = isset($element['#field_parents']) ? $element['#field_parents'] : array();
array_push($tablefield_parents, $element['#field_name'], $element['#language'], $element['#delta'], 'tablefield');
$id = drupal_clean_css_identifier(implode('-', $tablefield_parents));
// IDs to use for various buttons/wrapper for this element. When processing
// an AJAX request, these IDs are used to build the field stack so we know
// where the value we're adjusting is in the FormAPI array.
$ajax_wrapper_id = "{$id}-wrapper";
$rebuild_id = "{$id}-rebuild";
$import_id = "{$id}-import";
$pasted_id = "{$id}-pasted";
// Default table size.
$default_size['count_cols'] = isset($instance['default_value'][0]['tablefield']['rebuild']['count_cols']) ? $instance['default_value'][0]['tablefield']['rebuild']['count_cols'] : 5;
$default_size['count_rows'] = isset($instance['default_value'][0]['tablefield']['rebuild']['count_rows']) ? $instance['default_value'][0]['tablefield']['rebuild']['count_rows'] : 5;
$default_size['header_orientation'] = isset($instance['default_value'][0]['tablefield']['rebuild']['header_orientation']) ? $instance['default_value'][0]['tablefield']['rebuild']['header_orientation'] : 'Horizontal';
// Default table cell values.
$default_value = NULL;
// If there's a triggering element get the values from form state.
if (isset($form_state['triggering_element'])) {
if ($form_state['triggering_element']['#name'] == $rebuild_id) {
// Rebuilding table rows/cols.
$default_value = drupal_array_get_nested_value($form_state['tablefield_rebuild'], $tablefield_parents);
drupal_set_message(t('Table structure rebuilt.'), 'status', FALSE);
}
elseif ($form_state['triggering_element']['#name'] == $import_id) {
// Importing CSV data.
tablefield_import_csv($form, $form_state, $langcode, $import_id, $tablefield_parents);
$default_value = drupal_array_get_nested_value($form_state['input'], $tablefield_parents);
$identifier = implode('--', $tablefield_parents);
$form_state['_tablefield_imported_values'][$identifier] = $default_value;
}
elseif ($form_state['triggering_element']['#name'] == $pasted_id) {
// Importing pasted data.
tablefield_import_pasted($form, $form_state, $langcode, $pasted_id, $tablefield_parents);
$default_value = drupal_array_get_nested_value($form_state['input'], $tablefield_parents);
if (empty($default_value['rebuild'])) {
$default_value['rebuild'] = $default_size;
}
}
else {
// The triggering element is neither a rebuild nor an import
// e.g. a file upload.
$default_value = drupal_array_get_nested_value($form_state['input'], $tablefield_parents);
}
}
// If no values by now, get tablefield item value stored in database, if any.
if (!$default_value) {
// This could be set e.g. when using paragraphs module.
if (isset($items[$delta]['tablefield'])) {
$default_value = $items[$delta]['tablefield'];
}
elseif (isset($items[$delta]['value'])) {
$default_value = unserialize($items[$delta]['value']);
}
elseif ($delta === 0 && isset($instance['default_value'][0]['tablefield'])) {
$default_value = $instance['default_value'][0]['tablefield'];
}
}
if (empty($default_value['rebuild'])) {
$default_value['rebuild'] = $default_size;
}
else {
// If this is data that was saved before 'header_orientation' was a
// per-value setting, then we need to keep the valuef from $default_size.
if (empty($default_value['rebuild']['header_orientation'])) {
$default_value['rebuild']['header_orientation'] = $default_size['header_orientation'];
}
$default_size = $default_value['rebuild'];
}
$count_rows = $default_size['count_rows'];
$count_cols = $default_size['count_cols'];
$header_orientation = $default_size['header_orientation'];
// Now we can build the widget.
$help_text = '';
if (!empty($instance['description'])) {
$help_text = $instance['description'];
}
else {
if ($settings) {
$display_settings = l(t('default display settings'), 'admin/structure/types/manage/' . $element['#bundle'] . '/display', array(
'attributes' => array(
'title' => t('Manage display settings'),
),
));
if ($hide_header == TRUE) {
$help_text = t('This table will not have a header according to the !display_settings.', array(
'!display_settings' => $display_settings,
));
}
else {
$help_text = t('The first row will appear as the table header. Leave the first row blank if you do not need a header.');
}
}
}
$element['tablefield'] = array(
'#title' => $element['#title'],
'#description' => filter_xss_admin($help_text),
'#attributes' => array(
'id' => $id,
'class' => array(
'form-tablefield',
),
),
'#type' => 'fieldset',
'#tree' => TRUE,
'#collapsible' => FALSE,
'#prefix' => '<div id="' . $ajax_wrapper_id . '">',
'#suffix' => '</div>',
);
if ($settings) {
if ($hide_header) {
$element['tablefield']['#attributes']['class'][] = 'table-no-headers';
}
}
if (in_array($header_orientation, array(
'Horizontal',
'Both',
))) {
$element['tablefield']['#attributes']['class'][] = 'tablefield-header-orientation-horizontal';
}
if (in_array($header_orientation, array(
'Vertical',
'Both',
))) {
$element['tablefield']['#attributes']['class'][] = 'tablefield-header-orientation-vertical';
}
// Give the fieldset the appropriate class if it is required.
if ($element['#required']) {
$element['tablefield']['#title'] .= ' <span class="form-required" title="';
$element['tablefield']['#title'] .= t('This field is required');
$element['tablefield']['#title'] .= '">*</span>';
}
if (arg(0) == 'admin') {
$element['tablefield']['#description'] = t('This form defines the table field defaults, but the number of rows/columns and content can be overridden.');
if ($settings) {
if (!$hide_header) {
$element['tablefield']['#description'] .= ' ' . t('The first row will appear as the table header. Leave the first row blank if you do not need a header.');
}
}
}
// Render the form table.
$element['tablefield']['tabledata']['a_break'] = array(
'#markup' => '<table id="tablefield-editor">',
);
$default_value = isset($default_value['tabledata']) ? $default_value['tabledata'] : $default_value;
// Make added default values visible when editing existing content.
if (isset($instance['widget']['settings']['restrict_rebuild']) && $instance['widget']['settings']['restrict_rebuild'] && $instance['widget']['settings']['lock_values'] && arg(0) !== 'admin' && arg(0) !== 'system') {
// Use the default number of cols/rows if they changed.
$count_cols = $count_cols != $instance['default_value'][0]['tablefield']['rebuild']['count_cols'] ? $instance['default_value'][0]['tablefield']['rebuild']['count_cols'] : $count_cols;
$count_rows = $count_rows != $instance['default_value'][0]['tablefield']['rebuild']['count_rows'] ? $instance['default_value'][0]['tablefield']['rebuild']['count_rows'] : $count_rows;
}
// Loop over all the rows.
for ($i = 0; $i < $count_rows; $i++) {
$zebra = $i % 2 == 0 ? 'even' : 'odd';
// Disable table drag functionality in case of locked default cells under
// the first row or completely on the field settings form.
$draggable = 'draggable ';
unset($instance['default_value'][0]['tablefield']['tabledata']["row_{$i}"]['weight']);
if (arg(0) == 'admin' || isset($instance['default_value'][0]['tablefield']['tabledata']["row_{$i}"]) && array_filter($instance['default_value'][0]['tablefield']['tabledata']["row_{$i}"])) {
$draggable = FALSE;
}
$element['tablefield']['tabledata']['b_break' . $i] = array(
'#markup' => '<tr class="' . $draggable . 'tablefield-row-' . $i . ' ' . $zebra . '"><td class="tablefield-row-count">' . ($i + 1) . '</td>',
);
// Loop over all the columns.
for ($ii = 0; $ii < $count_cols; $ii++) {
$instance_default = isset($instance['default_value'][0]['tablefield']['tabledata']["row_{$i}"]["col_{$ii}"]) ? $instance['default_value'][0]['tablefield']['tabledata']["row_{$i}"]["col_{$ii}"] : array();
if (!empty($instance_default) && !empty($instance['widget']['settings']['lock_values']) && arg(0) != 'admin') {
// The value still needs to be send on every load in order for the
// table to be saved correctly.
$element['tablefield']['tabledata']['row_' . $i]['col_' . $ii] = array(
'#type' => 'value',
'#value' => $instance_default,
);
// Display the default value, since it's not editable.
$element['tablefield']['tabledata']['row_' . $i]['col_' . $ii . '_display'] = array(
'#type' => 'item',
'#title' => $instance_default,
'#prefix' => '<td class="col-' . $ii . '">',
'#suffix' => '</td>',
);
}
else {
$input_type = isset($instance['widget']['settings']['input_type']) ? $instance['widget']['settings']['input_type'] : 'textfield';
$max_length = isset($instance['widget']['settings']['max_length']) ? abs($instance['widget']['settings']['max_length']) : '2048';
$cell_default = isset($default_value['row_' . $i]['col_' . $ii]) ? $default_value['row_' . $i]['col_' . $ii] : '';
// If the field does not contain HTML, is not plain text and a text area
// then covert linebreaks to <br />.
$format = isset($items[$delta]['format']) ? $items[$delta]['format'] : 'plain_text';
if (!($cell_default != strip_tags($cell_default)) && $format !== 'plain_text') {
$nl2br = array(
'_cell_validate',
);
}
else {
$nl2br = NULL;
}
$element['tablefield']['tabledata']['row_' . $i]['col_' . $ii] = array(
'#type' => $input_type,
'#maxlength' => $max_length,
'#size' => 0,
'#attributes' => array(
'id' => $id . '-cell-' . $i . '-' . $ii,
'class' => array(
'tablefield-row-' . $i,
'tablefield-col-' . $ii,
),
'style' => 'min-width: 100%',
),
'#default_value' => $cell_default,
'#prefix' => '<td class="col-' . $ii . '">',
'#suffix' => '</td>',
'#element_validate' => $nl2br,
);
}
}
// Add an extra column for the weight.
$row_weight_default = isset($default_value[$i]['weight']) ? $default_value[$i]['weight'] : $i + 1;
$element['tablefield']['tabledata']['row_' . $i]['weight'] = array(
'#type' => 'weight',
'#title' => t('Weight'),
'#default_value' => $row_weight_default,
'#delta' => $count_rows,
'#attributes' => array(
'class' => array(
'tablefield-weight',
),
),
'#prefix' => '<td class="tabledrag-hide">',
'#suffix' => '</td>',
);
$element['tablefield']['c_break' . $i] = array(
'#markup' => '</tr>',
);
}
$element['tablefield']['t_break' . $i] = array(
'#markup' => '</table>',
);
// Provide caption field to describe the data contained in the table.
$element['tablefield']['caption'] = array(
'#type' => 'textfield',
'#title' => t('Table description'),
'#default_value' => '',
'#description' => t('This brief caption will be associated with the table and will help Assistive Technology, like screen readers, better describe the content within.'),
);
// Could be the Paragraphs module.
if (isset($items[$delta]['tablefield'])) {
$raw = $items[$delta]['tablefield'];
}
elseif (isset($items[$delta]['value'])) {
$raw = unserialize($items[$delta]['value']);
}
elseif ($delta === 0 && isset($instance['default_value'][0]['tablefield'])) {
$raw = $instance['default_value'][0]['tablefield'];
}
if (isset($raw['caption'])) {
$element['tablefield']['caption']['#default_value'] = check_plain($raw['caption']);
}
// If the user doesn't have rebuild perms, we pass along the data as a value.
// Otherwise we provide form elements to specify the size and ajax rebuild.
if (isset($instance['widget']['settings']['restrict_rebuild']) && $instance['widget']['settings']['restrict_rebuild'] && !user_access('rebuild tablefield') || isset($instance['widget']['settings']['restrict_rebuild']) && $instance['widget']['settings']['restrict_rebuild'] && $instance['widget']['settings']['lock_values'] && arg(0) !== 'admin' && arg(0) !== 'system') {
$element['tablefield']['rebuild'] = array(
'#type' => 'value',
'#tree' => TRUE,
'count_cols' => array(
'#type' => 'value',
'#value' => $count_cols,
),
'count_rows' => array(
'#type' => 'value',
'#value' => $count_rows,
),
'header_orientation' => array(
'#type' => 'value',
'#value' => $header_orientation,
),
'rebuild' => array(
'#type' => 'value',
'#value' => t('Rebuild Table'),
),
);
}
else {
$element['tablefield']['rebuild'] = array(
'#type' => 'fieldset',
'#tree' => TRUE,
'#title' => t('Number of rows/columns and header orientation'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$element['tablefield']['rebuild']['count_cols'] = array(
'#title' => t('How many Columns'),
'#type' => 'textfield',
'#size' => 5,
'#prefix' => '<div class="clearfix">',
'#suffix' => '</div>',
'#value' => $count_cols,
);
$element['tablefield']['rebuild']['count_rows'] = array(
'#title' => t('How many Rows'),
'#type' => 'textfield',
'#size' => 5,
'#prefix' => '<div class="clearfix">',
'#suffix' => '</div>',
'#value' => $count_rows,
);
$element['tablefield']['rebuild']['header_orientation'] = array(
'#type' => 'select',
'#title' => t('Header orientation'),
'#options' => array(
'Horizontal' => t('First row (horizontal)'),
'Vertical' => t('First column (vertical)'),
'Both' => t('Both first row and first column (two headers, horizontal and vertical)'),
),
'#default_value' => $header_orientation,
);
$element['tablefield']['rebuild']['rebuild'] = array(
'#type' => 'button',
'#validate' => array(),
'#limit_validation_errors' => array(),
'#executes_submit_callback' => TRUE,
'#submit' => array(
'tablefield_rebuild_form',
),
'#value' => t('Rebuild Table'),
'#name' => $rebuild_id,
'#attributes' => array(
'class' => array(
'tablefield-rebuild',
),
),
'#ajax' => array(
'callback' => 'tablefield_rebuild_form_ajax',
'wrapper' => $ajax_wrapper_id,
'effect' => 'fade',
),
);
}
if (user_access('always use additional datasources') || isset($instance['widget']['settings']['data_sources']['upload']) && $instance['widget']['settings']['data_sources']['upload'] === 'upload') {
// Allow the user to import a csv file.
$element['tablefield']['import'] = array(
'#type' => 'fieldset',
'#tree' => TRUE,
'#title' => t('Upload CSV file'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$element['tablefield']['import']['file'] = array(
'#name' => 'files[' . $import_id . ']',
'#title' => t('File upload'),
'#type' => 'file',
);
$element['tablefield']['import']['import'] = array(
'#type' => 'button',
'#validate' => array(),
'#limit_validation_errors' => array(),
'#executes_submit_callback' => TRUE,
'#submit' => array(
'tablefield_rebuild_form',
),
'#value' => t('Upload CSV'),
'#name' => $import_id,
'#attributes' => array(
'class' => array(
'tablefield-rebuild',
),
),
'#ajax' => array(
'callback' => 'tablefield_rebuild_form_ajax',
'wrapper' => $ajax_wrapper_id,
'effect' => 'fade',
),
);
}
if (user_access('always use additional datasources') || isset($instance['widget']['settings']['data_sources']['paste']) && $instance['widget']['settings']['data_sources']['paste'] === 'paste') {
// Allow user to paste data (e.g. from Excel).
$element['tablefield']['paste'] = array(
'#type' => 'fieldset',
'#tree' => TRUE,
'#title' => t('Copy & Paste'),
'#attributes' => array(
'class' => array(
'tablefield-extra tablefield-paste',
),
),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$delimiters = array(
'TAB' => t('TAB'),
',' => t('Comma ,'),
';' => t('Semicolon ;'),
'|' => t('Pipe |'),
'+' => t('Plus +'),
':' => t('Colon :'),
);
$element['tablefield']['paste']['paste_delimiter'] = array(
'#type' => 'select',
'#tree' => TRUE,
'#title' => t('Column separator'),
'#name' => 'delimiter[' . $pasted_id . ']',
'#options' => $delimiters,
'#description' => t('Data copied from Excel will use TAB.'),
);
$element['tablefield']['paste']['data'] = array(
'#type' => 'textarea',
'#tree' => TRUE,
'#name' => 'data[' . $pasted_id . ']',
'#title' => t('Paste table data here:'),
);
$element['tablefield']['paste']['paste_import'] = array(
'#type' => 'button',
'#validate' => array(),
'#limit_validation_errors' => array(),
'#executes_submit_callback' => TRUE,
'#submit' => array(
'tablefield_rebuild_form',
),
'#value' => t('Import & Rebuild'),
'#name' => $pasted_id,
'#ajax' => array(
'callback' => 'tablefield_rebuild_form_ajax',
'wrapper' => $ajax_wrapper_id,
'effect' => 'fade',
),
);
}
// Allow the user to select input filters.
if (!empty($instance['widget']['settings']['cell_processing'])) {
$element['#base_type'] = $element['#type'];
$element['#type'] = 'text_format';
$element['#format'] = isset($items[$delta]['format']) ? $items[$delta]['format'] : NULL;
if (module_exists('wysiwyg')) {
$element['#wysiwyg'] = FALSE;
}
}
$form['element']['#element_validate'][] = 'tablefield_field_widget_form_validate';
return $element;
}