Skip to content

Instantly share code, notes, and snippets.

@and1truong
Created November 19, 2012 17:16
Show Gist options
  • Select an option

  • Save and1truong/4112012 to your computer and use it in GitHub Desktop.

Select an option

Save and1truong/4112012 to your computer and use it in GitHub Desktop.
<?php
function field_collection_remove_submit($form, &$form_state) {
$button = $form_state['triggering_element'];
$delta = $button['#delta'];
// Where in the form we'll find the parent element.
$address = array_slice($button['#array_parents'], 0, -2);
// Go one level up in the form, to the widgets container.
$parent_element = drupal_array_get_nested_value($form, $address);
$field_name = $parent_element['#field_name'];
$langcode = $parent_element['#language'];
$parents = $parent_element['#field_parents'];
$field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
$_field_state = drupal_array_get_nested_value($form_state['field']['#parents'], $address);
// Go ahead and renumber everything from our delta to the last
// item down one. This will overwrite the item being removed.
for ($i = $delta; $i < $field_state['items_count']; $i++) {
$old_element_address = array_merge($address, array($i + 1));
$new_element_address = array_merge($address, array($i));
$moving_element = drupal_array_get_nested_value($form, $old_element_address);
$moving_element_value = drupal_array_get_nested_value($form_state['values'], $old_element_address);
$moving_element_input = drupal_array_get_nested_value($form_state['input'], $old_element_address);
// Tell the element where it's being moved to.
$moving_element['#parents'] = $new_element_address;
// Move the element around.
form_set_value($moving_element, $moving_element_value, $form_state);
drupal_array_set_nested_value($form_state['input'], $moving_element['#parents'], $moving_element_input);
// Move the entity in our saved state.
if (isset($field_state['entity'][$i + 1])) {
$field_state['entity'][$i] = $field_state['entity'][$i + 1];
$_field_state[$i] = $_field_state[$i + 1];
}
else {
unset($field_state['entity'][$i]);
unset($_field_state[$i]);
}
}
// Replace the deleted entity with an empty one. This helps to ensure that
// trying to add a new entity won't ressurect a deleted entity from the
// trash bin.
$count = count($field_state['entity']);
$field_state['entity'][$count] = entity_create('field_collection_item', array('field_name' => $field_name));
// Then remove the last item. But we must not go negative.
if ($field_state['items_count'] > 0) {
$field_state['items_count']--;
}
// Fix the weights. Field UI lets the weights be in a range of
// (-1 * item_count) to (item_count). This means that when we remove one,
// the range shrinks; weights outside of that range then get set to
// the first item in the select by the browser, floating them to the top.
// We use a brute force method because we lost weights on both ends
// and if the user has moved things around, we have to cascade because
// if I have items weight weights 3 and 4, and I change 4 to 3 but leave
// the 3, the order of the two 3s now is undefined and may not match what
// the user had selected.
$input = drupal_array_get_nested_value($form_state['input'], $address);
// Sort by weight
uasort($input, '_field_sort_items_helper');
// Reweight everything in the correct order.
$weight = -1 * $field_state['items_count'];
foreach ($input as $key => $item) {
if ($item) {
$input[$key]['_weight'] = $weight++;
}
}
foreach ($field_state['entity'] as $i => $info) {
if (!$info->item_id) {
unset($field_state['entity'][$i]);
unset($_field_state['entity'][$i]);
}
}
drupal_array_set_nested_value($form_state['input'], $address, $input);
drupal_array_set_nested_value($form_state['field']['#parents'], $address, $_field_state);
field_form_set_state($parents, $field_name, $langcode, $form_state, $field_state);
$form_state['rebuild'] = TRUE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment