Skip to content
Snippets Groups Projects
Commit 4247ecd6 authored by Jeroen Bobbeldijk's avatar Jeroen Bobbeldijk
Browse files

Added functionality as described in #2138767

parent 8b9738b0
No related branches found
Tags 7.x-1.x-dev-editmode
No related merge requests found
......@@ -2,7 +2,7 @@
define('PARAGRAPHS_DEFAULT_TITLE', 'Paragraph');
define('PARAGRAPHS_DEFAULT_TITLE_MULTIPLE', 'Paragraphs');
define('PARAGRAPHS_DEFAULT_EDIT_MODE', 'open');
/**
* Loads a paragraphs item.
......@@ -682,6 +682,17 @@ function paragraphs_menu() {
'file' => 'paragraphs.admin.inc',
);
$items['paragraphs/edit/ajax'] = array(
'title' => 'Edit item callback',
'page callback' => 'paragraphs_edit_js',
'delivery callback' => 'ajax_deliver',
'access callback' => TRUE,
'theme callback' => 'ajax_base_page_theme',
'type' => MENU_CALLBACK,
'file path' => 'includes',
'file' => 'form.inc',
);
$items['paragraphs/remove/ajax'] = array(
'title' => 'Remove item callback',
'page callback' => 'paragraphs_remove_js',
......@@ -892,6 +903,19 @@ function paragraphs_field_instance_settings_form($field, $instance) {
'#required' => TRUE,
);
$element['default_edit_mode'] = array(
'#type' => 'select',
'#title' => t('Default edit mode'),
'#description' => t('The default edit mode the paragraph item is in.'),
'#options' => array(
'open' => t('Open'),
'closed' => t('Closed'),
),
'#default_value' => isset($settings['default_edit_mode']) ? $settings['default_edit_mode'] : PARAGRAPHS_DEFAULT_EDIT_MODE,
'#required' => TRUE,
);
if(!count($bundles)) {
$element['allowed_bundles_explain'] = array(
'#type' => 'markup',
......@@ -1247,10 +1271,22 @@ function paragraphs_field_widget_form_build(&$form, &$form_state, $field, $insta
$deleted_paragraph = FALSE;
$default_edit_mode = isset($instance['settings']['default_edit_mode']) ? $instance['settings']['default_edit_mode'] : PARAGRAPHS_DEFAULT_EDIT_MODE;
$being_edited_paragraph = TRUE;
if($default_edit_mode === 'closed') {
$being_edited_paragraph = FALSE;
}
if (isset($field_state['entity'][$delta])) {
if(isset($field_state['entity'][$delta]->removed) && $field_state['entity'][$delta]->removed) {
$deleted_paragraph = TRUE;
}
if($being_edited_paragraph || (isset($field_state['entity'][$delta]->being_edited) && $field_state['entity'][$delta]->being_edited)) {
$being_edited_paragraph = TRUE;
} else {
$being_edited_paragraph = FALSE;
}
$paragraph_item = $field_state['entity'][$delta];
}
else {
......@@ -1262,6 +1298,8 @@ function paragraphs_field_widget_form_build(&$form, &$form_state, $field, $insta
// load.
if (empty($paragraph_item) && $bundle) {
$paragraph_item = entity_create('paragraphs_item', array('bundle' => $bundle, 'field_name' => $field_name));
$paragraph_item->being_edited = TRUE;
$being_edited_paragraph = TRUE;
}
if (!empty($paragraph_item)) {
......@@ -1282,17 +1320,38 @@ function paragraphs_field_widget_form_build(&$form, &$form_state, $field, $insta
}
if(!$deleted_paragraph) {
field_attach_form('paragraphs_item', $paragraph_item, $element, $form_state, $language);
if (empty($element['#required'])) {
$element['#after_build'][] = 'paragraphs_field_widget_embed_delay_required_validation';
}
if (isset($paragraph_item)) {
$element['actions'] = array(
'#type' => 'actions',
'#weight' => 9999,
);
if($being_edited_paragraph) {
field_attach_form('paragraphs_item', $paragraph_item, $element, $form_state, $language);
if (empty($element['#required'])) {
$element['#after_build'][] = 'paragraphs_field_widget_embed_delay_required_validation';
}
} else {
$element['actions'] = array(
'#type' => 'actions',
'#weight' => 9999,
);
$element['actions']['edit_button'] = array(
'#delta' => $delta,
'#name' => implode('_', $parents) . '_edit_button',
'#type' => 'submit',
'#value' => t('Edit'),
'#validate' => array(),
'#submit' => array('paragraphs_edit_submit'),
'#limit_validation_errors' => array(),
'#ajax' => array(
'path' => 'paragraphs/edit/ajax',
'effect' => 'fade',
),
'#weight' => 999,
);
}
if (isset($paragraph_item)) {
$element['actions']['remove_button'] = array(
'#delta' => $delta,
'#name' => implode('_', $parents) . '_remove_button',
......@@ -1584,6 +1643,66 @@ function paragraphs_remove_submit($form, &$form_state) {
$form_state['rebuild'] = TRUE;
}
/**
* Submit callback to editing an item from the field UI multiple wrapper.
*
* When a edited button is submitted, we need to find the item that it
* referenced and delete it. Since field UI has the deltas as a straight
* unbroken array key, we have to renumber everything down. Since we do this
* we *also* need to move all the deltas around in the $form_state['values']
* and $form_state['input'] so that user changed values follow. This is a bit
* of a complicated process.
*/
function paragraphs_edit_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, -3);
// 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);
if(isset($field_state['entity'][$delta])) {
$field_state['entity'][$delta]->being_edited = 1;
}
// 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,
// but first remove garbage values to ensure proper '_weight' sorting
unset($input['add_more']);
uasort($input, '_field_sort_items_helper');
// Reweight everything in the correct order.
$weight = -1 * $field_state['items_count'] + 1;
foreach ($input as $key => $item) {
if ($item) {
$input[$key]['_weight'] = $weight++;
}
}
drupal_array_set_nested_value($form_state['input'], $address, $input);
field_form_set_state($parents, $field_name, $langcode, $form_state, $field_state);
$form_state['rebuild'] = TRUE;
}
/**
* Submit callback to remove an item from the field UI multiple wrapper.
*
......@@ -1727,6 +1846,49 @@ function paragraphs_restore_submit($form, &$form_state) {
}
/**
* Page callback to handle AJAX for editing a paragraphs item.
*
* This is a direct page callback. The actual job of deleting the item is
* done in the submit handler for the button, so all we really need to
* do is process the form and then generate output. We generate this
* output by doing a replace command on the id of the entire form element.
*/
function paragraphs_edit_js() {
// drupal_html_id() very helpfully ensures that all html IDS are unique
// on a page. Unfortunately what it doesn't realize is that the IDs
// we are generating are going to replace IDs that already exist, so
// this actually works against us.
if (isset($_POST['ajax_html_ids'])) {
unset($_POST['ajax_html_ids']);
}
list($form, $form_state) = ajax_get_form();
drupal_process_form($form['#form_id'], $form, $form_state);
// Get the information on what we're removing.
$button = $form_state['triggering_element'];
// Go two levels up in the form, to the whole widget.
$element = drupal_array_get_nested_value($form, array_slice($button['#array_parents'], 0, -4));
// Now send back the proper AJAX command to replace it.
$return = array(
'#type' => 'ajax',
'#commands' => array(
ajax_command_replace('#' . $element['#id'], drupal_render($element))
),
);
// Because we're doing this ourselves, messages aren't automatic. We have
// to add them.
$messages = theme('status_messages');
if ($messages) {
$return['#commands'][] = ajax_command_prepend('#' . $element['#id'], $messages);
}
return $return;
}
/**
* Page callback to handle AJAX for removing a paragraphs item.
*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment