Commit 36a7dd83 authored by catch's avatar catch

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
......@@ -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.');
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment