diff --git a/core/core.services.yml b/core/core.services.yml index c158be4..eadf9eb 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -110,7 +110,7 @@ services: arguments: [default] form_builder: class: Drupal\Core\Form\FormBuilder - arguments: ['@module_handler', '@keyvalue.expirable', '@event_dispatcher', '@url_generator', '@string_translation', '@?csrf_token', '@?http_kernel'] + arguments: ['@module_handler', '@keyvalue.expirable', '@config.factory', '@event_dispatcher', '@url_generator', '@string_translation', '@?csrf_token', '@?http_kernel'] calls: - [setRequest, ['@?request=']] keyvalue: diff --git a/core/includes/form.inc b/core/includes/form.inc index 8867456..e619643 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -171,8 +171,8 @@ function form_get_cache($form_build_id, &$form_state) { * * @see \Drupal\Core\Form\FormBuilderInterface::setCache(). */ -function form_set_cache($form_build_id, $form, $form_state) { - \Drupal::formBuilder()->setCache($form_build_id, $form, $form_state); +function form_set_cache($form_build_id, $form, $form_state, $expire = NULL) { + \Drupal::formBuilder()->setCache($form_build_id, $form, $form_state, $expire); } /** diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 7ae1360..504ecc0 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -459,6 +459,7 @@ function install_begin_request(&$install_state) { $container->register('form_builder', 'Drupal\Core\Form\FormBuilder') ->addArgument(new Reference('module_handler')) ->addArgument(new Reference('keyvalue.expirable')) + ->addArgument(new Reference('config.factory')) ->addArgument(new Reference('event_dispatcher')) ->addArgument(new Reference('url_generator')) ->addArgument(new Reference('string_translation')) diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php index 26a1c3d..af15f86 100644 --- a/core/lib/Drupal/Core/Form/FormBuilder.php +++ b/core/lib/Drupal/Core/Form/FormBuilder.php @@ -12,6 +12,7 @@ use Drupal\Component\Utility\Unicode; use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Access\CsrfTokenGenerator; +use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\HttpKernel; use Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface; @@ -54,6 +55,13 @@ class FormBuilder implements FormBuilderInterface { protected $eventDispatcher; /** + * The config factory used by the form caching mechanism. + * + * @var \Drupal\Core\Config\ConfigFactoryInterface + */ + protected $configFactory; + + /** * The URL generator. * * @var \Drupal\Core\Routing\UrlGeneratorInterface @@ -125,6 +133,8 @@ class FormBuilder implements FormBuilderInterface { * The module handler. * @param \Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface $key_value_expirable_factory * The keyvalue expirable factory. + * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory + * The config factory. * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher * The event dispatcher. * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator @@ -136,9 +146,10 @@ class FormBuilder implements FormBuilderInterface { * @param \Drupal\Core\HttpKernel $http_kernel * The HTTP kernel. */ - public function __construct(ModuleHandlerInterface $module_handler, KeyValueExpirableFactoryInterface $key_value_expirable_factory, EventDispatcherInterface $event_dispatcher, UrlGeneratorInterface $url_generator, TranslationInterface $translation_manager, CsrfTokenGenerator $csrf_token = NULL, HttpKernel $http_kernel = NULL) { + public function __construct(ModuleHandlerInterface $module_handler, KeyValueExpirableFactoryInterface $key_value_expirable_factory, ConfigFactoryInterface $config_factory, EventDispatcherInterface $event_dispatcher, UrlGeneratorInterface $url_generator, TranslationInterface $translation_manager, CsrfTokenGenerator $csrf_token = NULL, HttpKernel $http_kernel = NULL) { $this->moduleHandler = $module_handler; $this->keyValueExpirableFactory = $key_value_expirable_factory; + $this->configFactory = $config_factory; $this->eventDispatcher = $event_dispatcher; $this->urlGenerator = $url_generator; $this->translationManager = $translation_manager; @@ -389,9 +400,10 @@ public function getCache($form_build_id, &$form_state) { /** * {@inheritdoc} */ - public function setCache($form_build_id, $form, $form_state) { - // 6 hours cache life time for forms should be plenty. - $expire = 21600; + public function setCache($form_build_id, $form, $form_state, $expire = NULL) { + if (!isset($expire)) { + $expire = $this->$configFactory->get('system.performance')->get('cache.form.expire'); + } // Cache form structure. if (isset($form)) { diff --git a/core/lib/Drupal/Core/Form/FormBuilderInterface.php b/core/lib/Drupal/Core/Form/FormBuilderInterface.php index 9166f98..e857d87 100644 --- a/core/lib/Drupal/Core/Form/FormBuilderInterface.php +++ b/core/lib/Drupal/Core/Form/FormBuilderInterface.php @@ -265,7 +265,7 @@ public function getCache($form_build_id, &$form_state); /** * Stores a form in the cache. */ - public function setCache($form_build_id, $form, $form_state); + public function setCache($form_build_id, $form, $form_state, $expire = NULL); /** * Retrieves, populates, and processes a form. diff --git a/core/modules/system/config/schema/system.schema.yml b/core/modules/system/config/schema/system.schema.yml index 6b82e60..30d543b 100644 --- a/core/modules/system/config/schema/system.schema.yml +++ b/core/modules/system/config/schema/system.schema.yml @@ -195,6 +195,13 @@ system.performance: max_age: type: integer label: 'Max age of page cache' + form: + type: mapping + label: 'Form cache settings' + mapping: + expire: + type: integer + label: 'Form cache timeout' css: type: mapping label: 'CSS performance settings' diff --git a/core/modules/system/config/system.performance.yml b/core/modules/system/config/system.performance.yml index 29b434b..c006149 100644 --- a/core/modules/system/config/system.performance.yml +++ b/core/modules/system/config/system.performance.yml @@ -2,6 +2,8 @@ cache: page: use_internal: false max_age: 0 + form: + expire: 21600 css: preprocess: false gzip: true diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/FormCacheTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/FormCacheTest.php index 0e6d629..fddb2e7 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Form/FormCacheTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Form/FormCacheTest.php @@ -22,6 +22,13 @@ class FormCacheTest extends DrupalUnitTestBase { */ public static $modules = array('system', 'user'); + /** + * An expiry period in seconds for form expirable state records. + * + * @var int + */ + protected $cache_expiry = 21600; + public static function getInfo() { return array( 'name' => 'Form cache tests', @@ -33,6 +40,7 @@ public static function getInfo() { public function setUp() { parent::setUp(); $this->installSchema('system', array('key_value_expire')); + $this->installConfig(array('system')); $this->form_build_id = $this->randomName(); $this->form = array( @@ -47,7 +55,7 @@ public function setUp() { */ function testCacheToken() { $this->container->set('current_user', new UserSession(array('uid' => 1))); - form_set_cache($this->form_build_id, $this->form, $this->form_state); + form_set_cache($this->form_build_id, $this->form, $this->form_state, $this->cache_expiry); $cached_form_state = form_state_defaults(); $cached_form = form_get_cache($this->form_build_id, $cached_form_state); @@ -78,7 +86,7 @@ function testNoCacheToken() { $this->container->set('current_user', new UserSession(array('uid' => 0))); $this->form_state['example'] = $this->randomName(); - form_set_cache($this->form_build_id, $this->form, $this->form_state); + form_set_cache($this->form_build_id, $this->form, $this->form_state, $this->cache_expiry); $cached_form_state = form_state_defaults(); $cached_form = form_get_cache($this->form_build_id, $cached_form_state); diff --git a/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php b/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php index 487f4c8..6de7462 100644 --- a/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php +++ b/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php @@ -41,6 +41,9 @@ public function setUp() { $container = new ContainerBuilder(); $container->set('url_generator', $this->urlGenerator); + $container->set('config.factory', $this->getConfigFactoryStub(array( + 'system.performance' => array('cache.form.expire' => 21600), + ))); \Drupal::setContainer($container); } diff --git a/core/tests/Drupal/Tests/Core/Form/FormTestBase.php b/core/tests/Drupal/Tests/Core/Form/FormTestBase.php index 3b7a97f..018af33 100644 --- a/core/tests/Drupal/Tests/Core/Form/FormTestBase.php +++ b/core/tests/Drupal/Tests/Core/Form/FormTestBase.php @@ -91,6 +91,14 @@ */ protected $keyValueExpirableFactory; + + /** + * The config factory. + * + * @var \Drupal\Core\Config\ConfigFactoryInterface + */ + protected $configFactory; + /** * @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\StringTranslation\TranslationInterface */ @@ -116,6 +124,10 @@ public function setUp() { array('form_state', $this->formStateCache), ))); + $this->configFactory = $this->getConfigFactoryStub(array( + 'system.performance' => array('cache.form.expire' => 21600), + )); + $this->eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->urlGenerator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface'); $this->translationManager = $this->getStringTranslationStub(); @@ -142,7 +154,7 @@ protected function tearDown() { * Sets up a new form builder object to test. */ protected function setupFormBuilder() { - $this->formBuilder = new TestFormBuilder($this->moduleHandler, $this->keyValueExpirableFactory, $this->eventDispatcher, $this->urlGenerator, $this->translationManager, $this->csrfToken, $this->httpKernel); + $this->formBuilder = new TestFormBuilder($this->moduleHandler, $this->keyValueExpirableFactory, $this->configFactory, $this->eventDispatcher, $this->urlGenerator, $this->translationManager, $this->csrfToken, $this->httpKernel); $this->formBuilder->setRequest($this->request); $this->formBuilder->setCurrentUser($this->account); }