diff --git a/authcache.formtokenids.js b/authcache.formtokenids.js index 0fe22a5..8dab6c2 100644 --- a/authcache.formtokenids.js +++ b/authcache.formtokenids.js @@ -20,4 +20,26 @@ }); } }; + + Drupal.behaviors.authcacheFormBuildId = { + attach: function (context, settings) { + if ($.isEmptyObject(settings.authcacheFormTokenIds)) { + return; + } + + // Retrieve new build id using an AJAX command. + $.AuthcacheAjax.cmd('form_build_id', settings.authcacheFormBuildIds, function(evt, result) { + if ($.isEmptyObject(result)) { + return; + } + + // Inject the hidden form_build_id input after each hidden form_id input. + $("form input[name='form_id']", context).once('authcacheFormBuildIds').after(function() { + if (settings.authcacheFormBuildIds[this.value] && result[this.value]) { + return "" + } + }); + }); + } + }; }(jQuery)); diff --git a/authcache.info b/authcache.info index 2ea5296..7695546 100644 --- a/authcache.info +++ b/authcache.info @@ -4,4 +4,5 @@ package = Performance and scalability core = 7.x configure = admin/config/system/authcache files[] = includes/AuthcacheFormTokenIdCommand.inc +files[] = includes/AuthcacheFormBuildIdCommand.inc files[] = includes/AuthcacheMenuLocalTasksCommand.inc diff --git a/authcache.module b/authcache.module index e1bd60b..ad3872f 100644 --- a/authcache.module +++ b/authcache.module @@ -203,6 +203,8 @@ function authcache_form_alter(&$form, &$form_state, $form_id) { * @see drupal_build_form(). */ function _authcache_form_after_build($form, $form_state) { + global $user; + $form_id = $form['#form_id']; if (isset($form['form_token']) && !authcache_get_request_property('ajax')) { @@ -215,6 +217,23 @@ function _authcache_form_after_build($form, $form_state) { unset($form['form_build_id']); unset($form['#build_id']); } + elseif ($user->uid) { + // Remove the build-id hidden field + unset($form['form_build_id']); + + // Otherwise store prototype-form builds in the cache for authenticated + // users. + drupal_add_js(drupal_get_path('module', 'authcache') . '/authcache.formtokenids.js'); + drupal_add_js(array('authcacheFormBuildIds' => array( + $form_id => $form['#build_id'], + )), 'setting'); + authcache_ajax_add_command('form_build_id'); + + // Prepend 'authcache-' to the build-id. Those builds will serve as + // prototypes when generating new forms for other users from within + // AuthcacheFormBuildIdCommand. + $form['#build_id'] = 'authcache-' . $form['#build_id']; + } if (isset($form['form_token']) && authcache_get_request_property('ajax')) { // Remove CSRF-token from built form and make sure it can be retrieved @@ -1265,6 +1284,13 @@ function authcache_authcache_ajax_command() { 'maxage' => ini_get('session.cookie_lifetime') ?: 0, ), ), + 'form_build_id' => array( + 'handler' => 'AuthcacheFormBuildIdCommand', + 'request' => 'formbuild', + 'request config' => array( + 'maxage' => 21600, + ), + ), 'menu_local_tasks' => array( 'handler' => 'AuthcacheMenuLocalTasksCommand', 'handler config' => array( diff --git a/includes/AuthcacheFormBuildIdCommand.inc b/includes/AuthcacheFormBuildIdCommand.inc new file mode 100644 index 0000000..5f922a2 --- /dev/null +++ b/includes/AuthcacheFormBuildIdCommand.inc @@ -0,0 +1,43 @@ + $form_build_id) { + // Retrieve prototype from form cache. Authcache prototype forms are + // prefixed with "form_authcache-". + if ($cached = cache_get('form_authcache-' . $form_build_id, 'cache_form')) { + $form = $cached->data; + + global $user; + if ($form['#form_id'] == $form_id) { + if ($cached = cache_get('form_state_authcache-' . $form_build_id, 'cache_form')) { + $form_state = $cached->data; + + $new_build_id = 'form-' . drupal_hash_base64(uniqid(mt_rand(), TRUE) . mt_rand()); + $form['#build_id'] = $new_build_id; + $form['form_build_id']['#value'] = $new_build_id; + $form['form_build_id']['#id'] = $new_build_id; + + // Store new form for the current user in the form cache. Note that + // form_set_cache will replace the per-user #cache_token before + // storing it. + form_set_cache($new_build_id, $form, $form_state); + + // Report the new build-id back to the browser + $buildids[$form_id] = $new_build_id; + } + } + } + } + + return $buildids; + } +}