diff --git a/core/lib/Drupal/Core/Ajax/UpdateBuildIdCommand.php b/core/lib/Drupal/Core/Ajax/UpdateBuildIdCommand.php new file mode 100644 index 0000000..d57d488 --- /dev/null +++ b/core/lib/Drupal/Core/Ajax/UpdateBuildIdCommand.php @@ -0,0 +1,64 @@ +old = $old; + $this->new = $new; + } + + /** + * Implements Drupal\Core\Ajax\CommandInterface:render(). + */ + public function render() { + + return array( + 'command' => 'update_build_id', + 'old' => $this->old, + 'new' => $this->new, + ); + } + +} diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php index e7af769..3175b8d 100644 --- a/core/lib/Drupal/Core/Form/FormBuilder.php +++ b/core/lib/Drupal/Core/Form/FormBuilder.php @@ -388,7 +388,7 @@ public function setCache($form_build_id, $form, FormStateInterface $form_state) // Cache form state. if (\Drupal::config('system.performance')->get('cache.page.use_internal') && drupal_page_is_cacheable()) { - $form_state['build_info']['immutable'] = TRUE; + $form_state->addBuildInfo('immutable', TRUE); } // Store the known list of safe strings for form re-use. // @todo Ensure we are not storing an excessively large string list in: diff --git a/core/lib/Drupal/Core/Form/FormState.php b/core/lib/Drupal/Core/Form/FormState.php index 1073543..59e5192 100644 --- a/core/lib/Drupal/Core/Form/FormState.php +++ b/core/lib/Drupal/Core/Form/FormState.php @@ -66,6 +66,12 @@ class FormState implements FormStateInterface, \ArrayAccess { * processed. * - base_form_id: Identification for a base form, as declared in the form * class's \Drupal\Core\Form\BaseFormIdInterface::getBaseFormId() method. + * - immutable: If this flag is set to TRUE, a new form build id is + * generated when the form is loaded from the cache. If it is subsequently + * saved to the cache again, it will have another cache id and therefore + * the original form and form-state will remain unaltered. This is + * important when page caching is enabled in order to prevent form state + * from leaking between anonymous users. * * @var array */ @@ -408,18 +414,6 @@ class FormState implements FormStateInterface, \ArrayAccess { protected $submit_handlers; /** - * If this flag is set to TRUE, a new form build id is generated when the form - * is loaded from the cache. If it is subsequently saved to the cache again, - * it will have another cache id and therefore the original form and - * form-state will remain unaltered. This is important when page caching is - * enabled in order to prevent form state from leaking between anonymous - * users. - * - * @var boolean - */ - protected $immutable; - - /** * Constructs a \Drupal\Core\Form\FormState object. * * @param array $form_state_additions diff --git a/core/misc/ajax.js b/core/misc/ajax.js index 7097bc0..5e15559 100644 --- a/core/misc/ajax.js +++ b/core/misc/ajax.js @@ -721,7 +721,7 @@ /** * Command to update a form's build ID. */ - updateBuildId: function(ajax, response, status) { + update_build_id: function(ajax, response, status) { $('input[name="form_build_id"][value="' + response.old + '"]').val(response.new); }, diff --git a/core/modules/file/src/Controller/FileWidgetAjaxController.php b/core/modules/file/src/Controller/FileWidgetAjaxController.php index 36f8b19..e674080 100644 --- a/core/modules/file/src/Controller/FileWidgetAjaxController.php +++ b/core/modules/file/src/Controller/FileWidgetAjaxController.php @@ -79,7 +79,9 @@ public function upload(Request $request) { $settings = drupal_merge_js_settings($js['settings']['data']); $response = new AjaxResponse(); - // TODO: Add commands. + foreach ($commands as $command) { + $response->addCommand($command, TRUE); + } return $response->addCommand(new ReplaceCommand(NULL, $output, $settings)); } diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php index 9c6585a..126d8a8 100644 --- a/core/modules/simpletest/src/WebTestBase.php +++ b/core/modules/simpletest/src/WebTestBase.php @@ -1900,7 +1900,7 @@ protected function drupalProcessAjaxResponse($content, array $ajax_response, arr break; case 'add_css': break; - case 'updateBuildId': + case 'update_build_id': $buildId = $xpath->query('//input[@name="form_build_id" and @value="' . $command['old'] . '"]')->item(0); if ($buildId) { $buildId->setAttribute('value', $command['new']); diff --git a/core/modules/system/src/Controller/FormAjaxController.php b/core/modules/system/src/Controller/FormAjaxController.php index 8659b10..c332833 100644 --- a/core/modules/system/src/Controller/FormAjaxController.php +++ b/core/modules/system/src/Controller/FormAjaxController.php @@ -8,6 +8,7 @@ namespace Drupal\system\Controller; use Drupal\Core\Ajax\AjaxResponse; +use Drupal\Core\Ajax\UpdateBuildIdCommand; use Drupal\Core\Form\FormState; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Psr\Log\LoggerInterface; @@ -129,7 +130,7 @@ protected function getForm(Request $request) { $commands = array(); if (isset($form['#build_id_old']) && $form['#build_id_old'] != $form['#build_id']) { // If the form build ID has changed, issue an Ajax command to update it. - $commands[] = $this->ajax_command_update_build_id($form); + $commands[] = new UpdateBuildIdCommand($form['#build_id_old'], $form['#build_id']); $form_build_id = $form['#build_id']; } @@ -150,28 +151,4 @@ protected function getForm(Request $request) { return array($form, $form_state, $form_id, $form_build_id, $commands); } - /** - * Creates a Drupal Ajax 'update_build_id' command. - * - * This command updates the value of a hidden form_build_id input element on a - * form. It requires the form passed in to have keys for both the old build ID - * in #build_id_old and the new build ID in #build_id. - * - * The primary use case for this Ajax command is to serve a new build ID to a - * form served from the cache to an anonymous user, preventing one anonymous - * user from accessing the form state of another anonymous users on Ajax enabled - * forms. - * - * @param array $form - * The form array representing the form whose build ID should be updated. - * @return array - * An array representing a updateBuildId command. - */ - private function ajax_command_update_build_id(array $form) { - return array( - 'command' => 'updateBuildId', - 'old' => $form['#build_id_old'], - 'new' => $form['#build_id'], - ); - } } diff --git a/core/modules/system/src/Tests/Ajax/AjaxFormPageCacheTest.php b/core/modules/system/src/Tests/Ajax/AjaxFormPageCacheTest.php index a94f4eb..88fd61e 100644 --- a/core/modules/system/src/Tests/Ajax/AjaxFormPageCacheTest.php +++ b/core/modules/system/src/Tests/Ajax/AjaxFormPageCacheTest.php @@ -13,7 +13,10 @@ class AjaxFormPageCacheTest extends AjaxTestBase { public function setUp() { parent::setUp(); - \Drupal::config('system.performance')->set('cache.page.use_internal', TRUE)->save(); + $config = \Drupal::config('system.performance'); + $config->set('cache.page.use_internal', 1); + $config->set('cache.page.max_age', 300); + $config->save(); } /** @@ -38,7 +41,7 @@ public function testSimpleAJAXFormValue() { $build_id_first_ajax = $this->getFormBuildId(); $this->assertNotEqual($build_id_initial, $build_id_first_ajax, 'Build id is changed in the simpletest-DOM on first AJAX submission'); $expected = array( - 'command' => 'updateBuildId', + 'command' => 'update_build_id', 'old' => $build_id_initial, 'new' => $build_id_first_ajax, ); @@ -61,7 +64,7 @@ public function testSimpleAJAXFormValue() { $this->assertNotEqual($build_id_from_cache_initial, $build_id_from_cache_first_ajax, 'Build id is changed in the simpletest-DOM on first AJAX submission'); $this->assertNotEqual($build_id_first_ajax, $build_id_from_cache_first_ajax, 'Build id from first user is not reused'); $expected = array( - 'command' => 'updateBuildId', + 'command' => 'update_build_id', 'old' => $build_id_from_cache_initial, 'new' => $build_id_from_cache_first_ajax, ); diff --git a/core/modules/system/src/Tests/Form/FormStoragePageCacheTest.php b/core/modules/system/src/Tests/Form/FormStoragePageCacheTest.php index d718758..524b3de 100644 --- a/core/modules/system/src/Tests/Form/FormStoragePageCacheTest.php +++ b/core/modules/system/src/Tests/Form/FormStoragePageCacheTest.php @@ -16,7 +16,10 @@ class FormStoragePageCacheTest extends WebTestBase { public function setUp() { parent::setUp(); - \Drupal::config('system.performance')->set('cache.page.use_internal', TRUE)->save(); + $config = \Drupal::config('system.performance'); + $config->set('cache.page.use_internal', 1); + $config->set('cache.page.max_age', 300); + $config->save(); } /**