diff --git a/core/includes/form.inc b/core/includes/form.inc index 3ebaca1..e3ae228 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -530,14 +530,12 @@ function drupal_rebuild_form($form_id, &$form_state, $old_form = NULL) { * Fetches a form from the cache. */ function form_get_cache($form_build_id, &$form_state) { - if ($cached = cache('form')->get('form_' . $form_build_id)) { - $form = $cached->data; - + if ($form = Drupal::service('keyvalue.expirable')->get('form')->get($form_build_id)) { global $user; if ((isset($form['#cache_token']) && drupal_valid_token($form['#cache_token'])) || (!isset($form['#cache_token']) && !$user->uid)) { - if ($cached = cache('form')->get('form_state_' . $form_build_id)) { + if ($stored_form_state = Drupal::service('keyvalue.expirable')->get('form_state')->get($form_build_id)) { // Re-populate $form_state for subsequent rebuilds. - $form_state = $cached->data + $form_state; + $form_state = $stored_form_state + $form_state; // If the original form is contained in include files, load the files. // @see form_load_include() @@ -569,12 +567,12 @@ function form_set_cache($form_build_id, $form, $form_state) { if ($GLOBALS['user']->uid) { $form['#cache_token'] = drupal_get_token(); } - cache('form')->set('form_' . $form_build_id, $form, REQUEST_TIME + $expire); + Drupal::service('keyvalue.expirable')->get('form')->setWithExpire($form_build_id, $form, $expire); } // Cache form state. if ($data = array_diff_key($form_state, array_flip(form_state_keys_no_cache()))) { - cache('form')->set('form_state_' . $form_build_id, $data, REQUEST_TIME + $expire); + Drupal::service('keyvalue.expirable')->get('form_state')->setWithExpire($form_build_id, $data, $expire); } } @@ -916,15 +914,6 @@ function drupal_process_form($form_id, &$form, &$form_state) { // Execute form submit handlers. form_execute_handlers('submit', $form, $form_state); - // We'll clear out the cached copies of the form and its stored data - // here, as we've finished with them. The in-memory copies are still - // here, though. - $config = config('system.performance'); - if (!$config->get('cache.page.use_internal') && !empty($form_state['values']['form_build_id'])) { - cache('form')->delete('form_' . $form_state['values']['form_build_id']); - cache('form')->delete('form_state_' . $form_state['values']['form_build_id']); - } - // If batches were set in the submit handlers, we process them now, // possibly ending execution. We make sure we do not react to the batch // that is already being processed (if a batch operation performs a diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index d2e461e..b52f982 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -374,6 +374,14 @@ function install_begin_request(&$install_state) { )) ->addMethodCall('setUserAgent', array('Drupal (+http://drupal.org/)')); + // Register the expirable key value store used by form cache. + $container + ->register('keyvalue.expirable', 'Drupal\Core\KeyValueStore\KeyValueExpirableFactory') + ->addArgument(new Reference('service_container')); + $container + ->register('keyvalue.expirable.null', 'Drupal\Core\KeyValueStore\KeyValueNullExpirableFactory'); + $conf['keyvalue_expirable_default'] = 'keyvalue.expirable.null'; + Drupal::setContainer($container); } diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php index 91bba3c..19c533b 100644 --- a/core/lib/Drupal/Core/CoreBundle.php +++ b/core/lib/Drupal/Core/CoreBundle.php @@ -105,6 +105,14 @@ public function build(ContainerBuilder $container) { $container ->register('keyvalue.database', 'Drupal\Core\KeyValueStore\KeyValueDatabaseFactory') ->addArgument(new Reference('database')); + // Register the KeyValueStoreExpirable factory. + $container + ->register('keyvalue.expirable', 'Drupal\Core\KeyValueStore\KeyValueExpirableFactory') + ->addArgument(new Reference('service_container')); + $container + ->register('keyvalue.expirable.database', 'Drupal\Core\KeyValueStore\KeyValueDatabaseExpirableFactory') + ->addArgument(new Reference('database')) + ->addTag('needs_destruction'); $container->register('settings', 'Drupal\Component\Utility\Settings') ->setFactoryClass('Drupal\Component\Utility\Settings') diff --git a/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpirable.php b/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpirable.php index e989470..93cca8b 100644 --- a/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpirable.php +++ b/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpirable.php @@ -7,6 +7,7 @@ namespace Drupal\Core\KeyValueStore; +use Drupal\Core\DestructableInterface; use Drupal\Core\Database\Connection; use Drupal\Core\Database\Query\Merge; @@ -16,7 +17,7 @@ * This key/value store implementation uses the database to store key/value * data with an expire date. */ -class DatabaseStorageExpirable extends DatabaseStorage implements KeyValueStoreExpirableInterface { +class DatabaseStorageExpirable extends DatabaseStorage implements KeyValueStoreExpirableInterface, DestructableInterface { /** * The connection object for this storage. @@ -56,15 +57,6 @@ public function __construct($collection, Connection $connection, $table = 'key_v } /** - * Performs garbage collection as needed when destructing the storage object. - */ - public function __destruct() { - if ($this->needsGarbageCollection) { - $this->garbageCollection(); - } - } - - /** * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::getMultiple(). */ public function getMultiple(array $keys) { @@ -158,4 +150,13 @@ protected function garbageCollection() { ->execute(); } + /** + * Implements Drupal\Core\DestructableInterface::destruct(). + */ + public function destruct() { + if ($this->needsGarbageCollection) { + $this->garbageCollection(); + } + } + } diff --git a/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseExpirableFactory.php b/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseExpirableFactory.php index 08e673e..0d63988 100644 --- a/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseExpirableFactory.php +++ b/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseExpirableFactory.php @@ -7,6 +7,7 @@ namespace Drupal\Core\KeyValueStore; +use Drupal\Core\DestructableInterface; use Drupal\Core\Database\Connection; use Drupal\Core\Database\Database; use Drupal\Core\KeyValueStore\KeyValueDatabaseFactory; @@ -14,7 +15,14 @@ /** * Defines the key/value store factory for the database backend. */ -class KeyValueDatabaseExpirableFactory extends KeyValueDatabaseFactory { +class KeyValueDatabaseExpirableFactory extends KeyValueDatabaseFactory implements DestructableInterface { + + /** + * Holds references to each instantiation so they can be terminated. + * + * @var array + */ + protected $storages; /** * Constructs a new key/value expirable database storage object for a given @@ -28,6 +36,17 @@ class KeyValueDatabaseExpirableFactory extends KeyValueDatabaseFactory { * A key/value store implementation for the given $collection. */ public function get($collection) { - return new DatabaseStorageExpirable($collection, $this->connection); + $storage = new DatabaseStorageExpirable($collection, $this->connection); + $this->storages[] = $storage; + return $storage; + } + + /** + * Implements Drupal\Core\DestructableInterface::terminate(). + */ + public function destruct() { + foreach ($this->storages as $storage) { + $storage->destruct(); + } } } diff --git a/core/lib/Drupal/Core/KeyValueStore/KeyValueNullExpirableFactory.php b/core/lib/Drupal/Core/KeyValueStore/KeyValueNullExpirableFactory.php new file mode 100644 index 0000000..fa2dc82 --- /dev/null +++ b/core/lib/Drupal/Core/KeyValueStore/KeyValueNullExpirableFactory.php @@ -0,0 +1,27 @@ +collection = $collection; + } + + /** + * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::get(). + */ + public function get($key) { + return NULL; + } + + /** + * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::getMultiple(). + */ + public function getMultiple(array $keys) { + return array(); + } + + /** + * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::getAll(). + */ + public function getAll() { + return array(); + } + + /** + * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::set(). + */ + public function set($key, $value) { } + + /** + * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::setIfNotExists(). + */ + public function setIfNotExists($key, $value) { } + + /** + * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::setMultiple(). + */ + public function setMultiple(array $data) { } + + /** + * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::delete(). + */ + public function delete($key) { } + + /** + * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::deleteMultiple(). + */ + public function deleteMultiple(array $keys) { } + + /** + * Implements Drupal\Core\KeyValueStore\KeyValueStoreInterface::getCollectionName(). + */ + public function getCollectionName() { + return $this->collection; + } + + /** + * Implements Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface::setMultipleWithExpire(). + */ + public function setMultipleWithExpire(array $data, $expire) { } + + /** + * Implements Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface::setWithExpire(). + */ + public function setWithExpire($key, $value, $expire) { } + + /** + * Implements Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface::setWithExpireIfNotExists(). + */ + public function setWithExpireIfNotExists($key, $value, $expire) { } + +} diff --git a/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/GarbageCollectionTest.php b/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/GarbageCollectionTest.php index 6334382..82c52df 100644 --- a/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/GarbageCollectionTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/KeyValueStore/GarbageCollectionTest.php @@ -62,10 +62,10 @@ public function testGarbageCollection() { ->execute(); } - // Perform a new set operation and then manually unset the object to + // Perform a new set operation and then manually destruct the object to // trigger garbage collection. $store->setWithExpire('autumn', 'winter', rand(500, 1000000)); - unset($store); + $store->destruct(); // Query the database and confirm that the stale records were deleted. $result = db_query( diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 08a9fd9..81a5534 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -684,8 +684,6 @@ function system_schema() { $schema['cache_bootstrap']['description'] = 'Cache table for data required to bootstrap Drupal, may be routed to a shared memory cache.'; $schema['cache_config'] = $schema['cache']; $schema['cache_config']['description'] = 'Cache table for configuration data.'; - $schema['cache_form'] = $schema['cache']; - $schema['cache_form']['description'] = 'Cache table for the form system to store recently built forms and their storage data, to be used in subsequent page requests.'; $schema['cache_page'] = $schema['cache']; $schema['cache_page']['description'] = 'Cache table used to store compressed pages for anonymous users, if page caching is enabled.'; $schema['cache_menu'] = $schema['cache']; @@ -2195,6 +2193,13 @@ function system_update_8051() { } /** + * Remove {cache_form} table. + */ +function system_update_8052() { + db_drop_table('cache_form'); +} + +/** * @} End of "defgroup updates-7.x-to-8.x". * The next series of updates should start at 9000. */ diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 2c51ae0..bfb4309 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -3529,7 +3529,7 @@ function system_cron() { // Cleanup the flood. Drupal::service('flood')->garbageCollection(); - $cache_bins = array_merge(module_invoke_all('cache_flush'), array('form', 'menu')); + $cache_bins = array_merge(module_invoke_all('cache_flush'), array('menu')); foreach ($cache_bins as $bin) { cache($bin)->deleteExpired(); } diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterEqualityTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterEqualityTest.php index f0f4814..1b398e9 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterEqualityTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterEqualityTest.php @@ -38,7 +38,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('menu_router', 'variable')); + $this->installSchema('system', array('menu_router', 'variable', 'key_value_expire')); } function viewsData() { diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterInOperatorTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterInOperatorTest.php index fb154c1..0c1f32a 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterInOperatorTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterInOperatorTest.php @@ -39,7 +39,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('menu_router', 'variable')); + $this->installSchema('system', array('menu_router', 'variable', 'key_value_expire')); } function viewsData() { diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterNumericTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterNumericTest.php index e12c94a..a82d23f 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterNumericTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterNumericTest.php @@ -39,7 +39,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('menu_router', 'variable')); + $this->installSchema('system', array('menu_router', 'variable', 'key_value_expire')); } function viewsData() { diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterStringTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterStringTest.php index 57489bb..a573108 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterStringTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterStringTest.php @@ -38,7 +38,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('menu_router', 'variable')); + $this->installSchema('system', array('menu_router', 'variable', 'key_value_expire')); } function viewsData() {