Skip to content
Snippets Groups Projects
Commit 36a7dd83 authored by catch's avatar catch
Browse files

Issue #1901100 by Gábor Hojtsy, jessebeach, Wim Leers: Make Edit module work...

Issue #1901100 by Gábor Hojtsy, jessebeach, Wim Leers: Make Edit module work with TempStore, so revisions are not saved on all atomic field edits.
parent 164ac6d0
No related branches found
No related tags found
No related merge requests found
......@@ -14,6 +14,7 @@
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormInterface;
use Drupal\user\TempStoreFactory;
use Drupal\Core\Entity\EntityChangedInterface;
/**
* Builds and process a form for editing a single entity field.
......@@ -88,6 +89,14 @@ public function buildForm(array $form, array &$form_state, EntityInterface $enti
// Add the field form.
field_attach_form($form_state['entity'], $form, $form_state, $form_state['langcode'], array('field_name' => $form_state['field_name']));
// Add a dummy changed timestamp field to attach form errors to.
if ($entity instanceof EntityChangedInterface) {
$form['changed_field'] = array(
'#type' => 'hidden',
'#value' => $entity->getChangedTime(),
);
}
// Add a submit button. Give it a class for easy JavaScript targeting.
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array(
......@@ -139,6 +148,16 @@ protected function init(array &$form_state, EntityInterface $entity, $field_name
public function validateForm(array &$form, array &$form_state) {
$entity = $this->buildEntity($form, $form_state);
field_attach_form_validate($entity, $form, $form_state, array('field_name' => $form_state['field_name']));
// Do validation on the changed field as well and assign the error to the
// dummy form element we added for this. We don't know the name of this
// field on the entity, so we need to find it and validate it ourselves.
if ($changed_field_name = $this->getChangedFieldName($entity)) {
$changed_field_errors = $entity->$changed_field_name->validate();
if (count($changed_field_errors)) {
form_set_error('changed_field', $changed_field_errors[0]->getMessage());
}
}
}
/**
......@@ -213,4 +232,22 @@ protected function simplify(array &$form, array &$form_state) {
}
}
/**
* Finds the field name for the field carrying the changed timestamp, if any.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
*
* @return string|null
* The name of the field found or NULL if not found.
*/
protected function getChangedFieldName(EntityInterface $entity) {
foreach ($entity as $field_name => $field) {
$definition = $field->getDefinition();
if (isset($definition['property_constraints']['value']['EntityChanged'])) {
return $field_name;
}
}
}
}
......@@ -72,7 +72,7 @@ function setUp() {
/**
* Test the loading of Edit when a user doesn't have access to it.
*/
function testUserWithoutPermission() {
public function testUserWithoutPermission() {
$this->drupalLogin($this->author_user);
$this->drupalGet('node/1');
......@@ -129,7 +129,7 @@ function testUserWithoutPermission() {
*
* Also ensures lazy loading of in-place editors works.
*/
function testUserWithPermission() {
public function testUserWithPermission() {
$this->drupalLogin($this->editor_user);
$this->drupalGet('node/1');
......@@ -304,4 +304,46 @@ function testPseudoFields() {
$this->assertNoRaw('data-edit-id="node/1/edit_test_pseudo_field/und/default"');
}
/**
* Tests Edit on a node that was concurrently edited on the full node form.
*/
public function testConcurrentEdit() {
$this->drupalLogin($this->editor_user);
$post = array('nocssjs' => 'true') + $this->getAjaxPageStatePostData();
$response = $this->drupalPost('edit/form/' . 'node/1/body/und/full', 'application/vnd.drupal-ajax', $post);
$ajax_commands = drupal_json_decode($response);
// Prepare form values for submission. drupalPostAJAX() is not suitable for
// handling pages with JSON responses, so we need our own solution here.
$form_tokens_found = preg_match('/\sname="form_token" value="([^"]+)"/', $ajax_commands[0]['data'], $token_match) && preg_match('/\sname="form_build_id" value="([^"]+)"/', $ajax_commands[0]['data'], $build_id_match);
$this->assertTrue($form_tokens_found, 'Form tokens found in output.');
if ($form_tokens_found) {
$post = array(
'form_id' => 'edit_field_form',
'form_token' => $token_match[1],
'form_build_id' => $build_id_match[1],
'body[0][summary]' => '',
'body[0][value]' => '<p>Fine thanks.</p>',
'body[0][format]' => 'filtered_html',
'op' => t('Save'),
);
// Save the node on the regular node edit form.
$this->drupalPostForm('node/1/edit', array(), t('Save'));
// Ensure different save timestamps for field editing.
sleep(2);
// Submit field form and check response. Should throw a validation error
// because the node was changed in the meantime.
$response = $this->drupalPost('edit/form/' . 'node/1/body/und/full', 'application/vnd.drupal-ajax', $post);
$this->assertResponse(200);
$ajax_commands = drupal_json_decode($response);
$this->assertIdentical(2, count($ajax_commands), 'The field form HTTP request results in two AJAX commands.');
$this->assertIdentical('editFieldFormValidationErrors', $ajax_commands[1]['command'], 'The second AJAX command is an editFieldFormValidationErrors command.');
$this->assertTrue(strpos($ajax_commands[1]['data'], t('The content has either been modified by another user, or you have already submitted modifications. As a result, your changes cannot be saved.')), 'Error message returned to user.');
}
}
}
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