Problem/Motivation

Since #2040135: Caches dependent on simple config are only invalidated on form submissions, simple config (all config that aren't config entities) finally have cache tags!

Now we are finally able to associate cache tags of simple config that is used in the logic to render something.

Proposed resolution

Find all occurrences of using simple config in Drupal core that are used to render something. Every form, every render array that uses it, would ideally associate the appropriate cache tags.

If that's too much work, it'd be okay to only do it for forms that are going to be visible to end users (as opposed to only admins; many forms will only be visible to admins).

Remaining tasks

Find & replace them all!

User interface changes

None.

API changes

None.

Wanna help?

  1. Find more occurrences; search for $this->config( and \Drupal::config(), check whether it's in something that gets rendered (a form or another render array.
  2. Is this form or render array conceivably going to be shown to an anonymous user? If not, go back to step 1.
  3. Once you found another occurrence, look at the render array you're dealing with. Let's call it $build. Is it guaranteed to have an empty $build['#cache']['tags']? In that case, just do $build['#cache']['tags'] = $config->getCacheTags(). Is it possible that there already are cache tags? Then merge the simple config's cache tags with the existing cache tags: $build['#cache']['tags'] = Cache::mergeTags($build['#cache']['tags'], $config->getCacheTags());.
  4. Re-render the page (note that you might have to clear the render cache; while working on this, you might want to disable the render cache temporarily, see https://www.drupal.org/node/2259531) and verify that the X-Drupal-Cache-Tags header now contains the cache tag for the simple config. The cache tags listed in that header are sorted alphabetically. The cache tag you're looking for always begins with config:, plus whatever config is being used. So if the code does \Drupal::config('user.settings'), you'll want to make sure a config:user.settings cache tag is listed in the header.
  5. Congratulations! You've made Drupal 8 more cacheable :)
  6. Back to step 1, for more!
CommentFileSizeAuthor
#58 wherever_simple_config-2407765-58.patch20.9 KBWim Leers
#56 interdiff.txt6.94 KBamateescu
#55 wherever_simple_config-2407765-48.patch20.48 KBWim Leers
#49 interdiff-option-b.txt7.68 KBWim Leers
#49 wherever_simple_config-2407765-49_option_b.patch22.41 KBWim Leers
#49 interdiff-option-a.txt8.54 KBWim Leers
#49 wherever_simple_config-2407765-49_option_a.patch23.24 KBWim Leers
#48 interdiff.txt8.02 KBWim Leers
#48 wherever_simple_config-2407765-48.patch20.48 KBWim Leers
#43 wherever_simple_config-2407765-41.patch20.72 KBWim Leers
#41 interdiff.txt1.4 KBWim Leers
#41 wherever_simple_config-2407765-41.patch20.72 KBWim Leers
#40 interdiff.txt5.78 KBWim Leers
#40 wherever_simple_config-2407765-40.patch20.82 KBWim Leers
#40 wherever_simple_config-2407765-40-systembranding_cachetags_test_only.patch18.44 KBWim Leers
#37 interdiff.txt1.38 KBWim Leers
#37 wherever_simple_config-2407765-37.patch16.9 KBWim Leers
#34 interdiff.txt5.6 KBWim Leers
#34 wherever_simple_config-2407765-34.patch16.9 KBWim Leers
#31 wherever_simple_config-2407765-31.patch11.94 KBWim Leers
#28 interdiff.txt3.51 KBWim Leers
#28 wherever_simple_config-2407765-28.patch12 KBWim Leers
#27 interdiff-24-27.txt12.01 KBborisson_
#27 wherever_simple_config-2407765-27.patch12.84 KBborisson_
#24 interdiff-20-24.txt1.75 KBborisson_
#24 wherever_simple_config-2407765-24.patch21.31 KBborisson_
#20 interdiff-18-20.txt378 bytesborisson_
#20 wherever_simple_config-2407765-20.patch22.37 KBborisson_
#18 interdiff-16-18.txt550 bytesborisson_
#18 wherever_simple_config-2407765-18.patch22.21 KBborisson_
#15 wherever_simple_config-2407765-15.patch21.67 KBborisson_
#15 interdiff-12-15.txt10.99 KBborisson_
#12 wherever_simple_config-2407765-12.patch10.68 KBborisson_
#12 interdiff-9-12.txt5.54 KBborisson_
#9 wherever_simple_config-2407765-9.patch8.42 KBborisson_
#6 wherever_simple_config-2407765-6.patch5.56 KBborisson_
#4 interdiff.txt1.6 KBWim Leers
#4 use_simple_config_cache_tags-2407765-4.patch2.63 KBWim Leers
#1 use_simple_config_cache_tags-2407765-1.patch1.92 KBWim Leers
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Wim Leers’s picture

Issue summary: View changes
Issue tags: +Novice, +php-novice
FileSize
1.92 KB

To get started, here's an example; for AccountForm, which contains the user registration form, which is end-user facing. I've also included it in CommentViewBuilder, which renders comments, and is hence also end-user facing.

I've also included further info in the IS, in case you want to help.

Wim Leers’s picture

Status: Active » Needs review

Status: Needs review » Needs work

The last submitted patch, 1: use_simple_config_cache_tags-2407765-1.patch, failed testing.

Wim Leers’s picture

Status: Needs work » Needs review
FileSize
2.63 KB
1.6 KB

This should fix at least the majority of the test failures, if not all.

Anonymous’s picture

Assigned: Unassigned »
Issue tags: +SprintWeekend2015
borisson_’s picture

Worked on this together with pjonckiere at the sprint in Ghent. Changed cache tags in:
- core/modules/aggregator/src/Controller/AggregatorController.php
- core/modules/contact/src/Controller/ContactController.php
- core/modules/forum/src/Controller/ForumController.php
- core/modules/search/src/Controller/SearchController.php
- core/modules/user/src/Form/UserCancelForm.php
- core/modules/user/src/Form/UserLoginForm.php

Status: Needs review » Needs work

The last submitted patch, 6: wherever_simple_config-2407765-6.patch, failed testing.

Wim Leers’s picture

Patch looks great; thanks! :)

12 simple failures in a single test; could you fix those? :)

+++ b/core/modules/user/src/Form/UserLoginForm.php
@@ -78,6 +79,7 @@ public function getFormId() {
   public function buildForm(array $form, FormStateInterface $form_state) {
+
     // Display login form:

Unnecessary change.

borisson_’s picture

Status: Needs work » Needs review
FileSize
8.42 KB

Fixed unneeded changed line, test now passes for me locally.

Berdir’s picture

@borisson_: Please provide interdiffs when you make changes to patches, so that it is easier to review. See https://www.drupal.org/documentation/git/interdiff

Wim Leers’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/user/src/Form/UserLoginForm.php
    @@ -109,6 +110,8 @@ public function buildForm(array $form, FormStateInterface $form_state) {
    +    $form['#cache']['tags'] = Cache::mergeTags(isset($form['#cache']['tags']) ? $form['#cache']['tags'] : [],  $this->config('system.site')->getCacheTags());
    

    I think it'd be better if you did $config = $this->config('system.site') before it's used to build this form, then use it in the form, and then use $config here too. That prevents us leaving this here by accident when the system.site config is no longer needed.

  2. +++ b/core/modules/contact/src/Controller/ContactController.php
    @@ -104,6 +105,7 @@ public function contactSitePage(ContactFormInterface $contact_form = NULL) {
    +    $form['#cache']['tags'] = Cache::mergeTags(isset($form['#cache']['tags']) ? $form['#cache']['tags'] : [],  $this->config('contact.settings')->getCacheTags());
    
    +++ b/core/modules/forum/src/Controller/ForumController.php
    @@ -190,6 +191,7 @@ protected function build($forums, TermInterface $term, $topics = array(), $paren
    +    $build['#cache']['tags'] = Cache::mergeTags(isset($build['#cache']['tags']) ? $build['#cache']['tags'] : [],  $this->config('forum.settings')->getCacheTags());
    
    +++ b/core/modules/user/src/Form/UserCancelForm.php
    @@ -112,6 +113,8 @@ public function buildForm(array $form, FormStateInterface $form_state) {
    +    $form['#cache']['tags'] = Cache::mergeTags(isset($form['#cache']['tags']) ? $form['#cache']['tags'] : [],  $this->config('user.settings')->getCacheTags());
    

    Same in these places.

borisson_’s picture

Status: Needs work » Needs review
FileSize
5.54 KB
10.68 KB

Fixed remarks in #11, added interdiff this time, so Berdir is happy.

Wim Leers’s picture

Assigned: » Unassigned
Status: Needs review » Needs work

Awesome! Looking great :)

Now we still need the remaining ones to be converted. E.g. in CommentForm, TermForm, and more.

borisson_’s picture

Assigned: Unassigned » borisson_
borisson_’s picture

Status: Needs work » Needs review
FileSize
10.99 KB
21.67 KB

Added cache tags for the following files as well, couldn't find other forms where this is needed.
- core/modules/block/src/BlockForm.php
- core/modules/book/src/BookManager.php
- core/modules/book/src/Form/BookSettingsForm.php
- core/modules/comment/src/CommentForm.php
- core/modules/contact/src/ContactFormEditForm.php
- core/modules/language/src/Form/NegotiationSelectedForm.php
- core/modules/language/src/Form/NegotiationUrlForm.php
- core/modules/locale/src/Form/LocaleSettingsForm.php
- core/modules/taxonomy/src/TermForm.php

Status: Needs review » Needs work

The last submitted patch, 15: wherever_simple_config-2407765-15.patch, failed testing.

Wim Leers’s picture

Indeed, all remaining forms are admin-facing forms.

The only one that I can still find is UserController::resetPass(). That's also end-user facing. Other than that, this is ready, I think :)

borisson_’s picture

Status: Needs work » Needs review
FileSize
22.21 KB
550 bytes

Added password reset form. Will have alook at why the tests are failing in the meantime

aspilicious’s picture

Is it a good idea to add a mergeConfigCacheTags($form, $config_tags) in formBase?

borisson_’s picture

Found the problem that made alle tests fail.

The last submitted patch, 18: wherever_simple_config-2407765-18.patch, failed testing.

Wim Leers’s picture

Assigned: borisson_ » Berdir

#19: I've been asking myself the same question. Alternative idea: make FormBase::config() accept an optional $form parameter, which then automatically merges the cache tags. No extra hassle. But still easy to miss.
(It's always going to be easy to miss in the current architecture; we can only avoid that if we re-architect how forms are built; but that's too late at this point. All we can do is make it as simple/painless as possible.)
Assigning to Berdir to get his thoughts on this.

#20: hah, awesome fix :)

Berdir’s picture

Thanks for all your work on this.

A lot thinking out lout below, wondering which cache tags we really need.

Did not read everything, my sprint day is over now :)

  1. +++ b/core/modules/aggregator/src/Controller/AggregatorController.php
    @@ -173,6 +173,10 @@ public function adminOverview() {
         $build = $this->buildPageList($items);
    +
    +    $config = $this->config('system.site');
    +    $build['#cache']['tags'] = $config->getCacheTags();
    +
         $build['#attached']['feed'][] = array('aggregator/rss', $this->config('system.site')->get('name') . ' ' . $this->t('aggregator'));
    

    I'm not sure if we should do it here, but considering that we're now doing this, should we consider to go one step further and actually cache this, with a list cache tag for aggregator items? Possibly in a separate issue.

    The cache tag makes sense on a theoretical level, but if you think about it practically, this is the site name we are talking about. If we change the site name, then we have to invalidate every page anyway, because which page doesn't contain the site name? :)

    (Also wondering why this is not a view already :))

  2. +++ b/core/modules/block/src/BlockForm.php
    @@ -108,10 +109,11 @@ public static function create(ContainerInterface $container) {
        */
       public function form(array $form, FormStateInterface $form_state) {
         $entity = $this->entity;
    +    $config = $this->config('system.theme');
    

    I'm not sure I see why we need this in entity forms like this one?

    I can not think of a scenario where we would be able to cache this form, why bother with cache tags?

    Adding cache tags/code means we need test coverage usually, so we need a test scenario that makes sense (That's my answer to "Adding it doesn't hurt anything", it delays getting this issue in with the parts that we do need :)

  3. +++ b/core/modules/book/src/BookManager.php
    @@ -317,7 +317,8 @@ public function getBookParents(array $item, array $parent = array()) {
       protected function addParentSelectFormElements(array $book_link) {
    -    if ($this->configFactory->get('book.settings')->get('override_parent_selector')) {
    +    $config = $this->configFactory->get('book.settings');
    +    if ($config->get('override_parent_selector')) {
           return array();
    

    This is also stuff that is only used in node/backend forms, but it being a service could theoretically mean that it will be used publicly ;)

  4. +++ b/core/modules/book/src/Form/BookSettingsForm.php
    @@ -51,6 +52,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
         );
         $form['array_filter'] = array('#type' => 'value', '#value' => TRUE);
    +    $form['#cache']['tags'] = Cache::mergeTags(isset($form['#cache']['tags']) ? $form['#cache']['tags'] : [],  $config->getCacheTags());
    

    Uhm. This is a ConfigForm, and $config is the config we are editing. If this would make sense, then we would have to add this by default to all config edit forms (Hint: I do not think this makes sense :))

  5. +++ b/core/modules/comment/src/CommentForm.php
    @@ -207,6 +209,8 @@ public function form(array $form, FormStateInterface $form_state) {
         );
     
    +    $form['#cache']['tags'] = Cache::mergeTags(isset($form['#cache']['tags']) ? $form['#cache']['tags'] : [],  $config->getCacheTags());
    +
    

    CommentForm is something we might display to anonymous users, so this makes sense...

  6. +++ b/core/modules/comment/src/CommentViewBuilder.php
    @@ -154,7 +155,9 @@ public function buildComponents(array &$build, array $entities, array $displays,
           $account = comment_prepare_author($entity);
    -      if (\Drupal::config('user.settings')->get('signatures') && $account->getSignature()) {
    +      $config = \Drupal::config('user.settings');
    +      $build['#cache']['tags'] = Cache::mergeTags(isset($build['#cache']['tags']) ? $build['#cache']['tags'] : [],  $config->getCacheTags());
    +      if ($config->get('signatures') && $account->getSignature()) {
    

    This one makes sense, wondering if the test below is enough test coverage for this, possibly?

  7. +++ b/core/modules/contact/src/ContactFormEditForm.php
    @@ -34,7 +35,8 @@ public function form(array $form, FormStateInterface $form_state) {
     
         $contact_form = $this->entity;
    -    $default_form = $this->config('contact.settings')->get('default_form');
    +    $config = $this->config('contact.settings');
    +    $default_form = $config->get('default_form');
     
    

    Same here, can't see how we would ever cache this.

borisson_’s picture

Removed Cache tags for BlockForm.php, BookSettingsForm.php & ContactFormEditForm.php. I'll see if I can change the test for CommentViewBuilder.

Wim Leers’s picture

Issue summary: View changes

I can not think of a scenario where we would be able to cache this form, why bother with cache tags?

Hrm, right, I should've explained it that way in the IS. Only if the form could conceivably be seen by an anonymous user, which means it might end up in the page cache/Varnish, only then do we need this. Updated IS.

Adding cache tags/code means we need test coverage usually,

Technically, it doesn't hurt to have cache tags set for uncacheable forms. It doesn't hurt. But this is indeed a good reason to only add cache tags where we can envision it being shown to an anonymous user: otherwise, we'll have to write a whole lot of tests for little value.

Sorry, borisson_ :(


+++ b/core/modules/aggregator/src/Controller/AggregatorController.php
index 3ff21f6..8a204ed 100644
--- a/core/modules/block/src/BlockForm.php

+++ b/core/modules/book/src/BookManager.php
index 0db0dc5..dc05eb8 100644
--- a/core/modules/book/src/Form/BookSettingsForm.php

+++ b/core/modules/comment/src/Tests/CommentDefaultFormatterCacheTagsTest.php
index 420be7d..f027dbc 100644
--- a/core/modules/contact/src/ContactFormEditForm.php

As of #24, the changes in these files can also be reverted.

Berdir’s picture

I'm not sure about AggregatorController, that is actually frontend, it's just the fact that it is the site name that made me think about it. (which is displayed everywhere, so everything would need to be invalidated I guess, do we need to worry about that?)

CommentDefaultFormatterCacheTagsTest is actually correct I think, that's from the comment view builder, which is frontend and cached, no?

Also note that I didn't get past "c" (in the module/file list of the patch) in my review above, so reviewed the changes and rest of the file as well.

  1. +++ b/core/modules/block/src/BlockForm.php
    @@ -10,6 +10,7 @@
     use Drupal\block\Event\BlockEvents;
     use Drupal\Component\Utility\Html;
    +use Drupal\Core\Cache\Cache;
     use Drupal\Core\Entity\EntityForm;
     use Drupal\Core\Entity\EntityManagerInterface;
     use Drupal\Core\Executable\ExecutableManagerInterface;
    @@ -108,10 +109,11 @@ public static function create(ContainerInterface $container) {
    
    @@ -108,10 +109,11 @@ public static function create(ContainerInterface $container) {
        */
       public function form(array $form, FormStateInterface $form_state) {
         $entity = $this->entity;
    +    $config = $this->config('system.theme');
     
         // Store theme settings in $form_state for use below.
         if (!$theme = $entity->getTheme()) {
    -      $theme = $this->config('system.theme')->get('default');
    +      $theme = $config->get('default');
         }
    

    Those changes are no longer necessary.

  2. +++ b/core/modules/book/src/Form/BookSettingsForm.php
    @@ -7,6 +7,7 @@
    
    @@ -7,6 +7,7 @@
     
     namespace Drupal\book\Form;
     
    +use Drupal\Core\Cache\Cache;
     use Drupal\Core\Form\ConfigFormBase;
     use Drupal\Core\Form\FormStateInterface;
    

    Same.

  3. +++ b/core/modules/contact/src/ContactFormEditForm.php
    @@ -7,6 +7,7 @@
    +use Drupal\Core\Cache\Cache;
     use Drupal\Core\Config\ConfigFactoryInterface;
    
    @@ -34,7 +35,8 @@ public function form(array $form, FormStateInterface $form_state) {
         $contact_form = $this->entity;
    -    $default_form = $this->config('contact.settings')->get('default_form');
    +    $config = $this->config('contact.settings');
    +    $default_form = $config->get('default_form');
     
    

    Same :)

  4. +++ b/core/modules/language/src/Form/NegotiationSelectedForm.php
    +++ b/core/modules/language/src/Form/NegotiationUrlForm.php
    

    Those are also backend forms.

  5. +++ b/core/modules/locale/src/Form/LocaleSettingsForm.php
    @@ -85,6 +86,8 @@ public function buildForm(array $form, FormStateInterface $form_state) {
         );
     
    +    $form['#cache']['tags'] = Cache::mergeTags(isset($form['#cache']['tags']) ? $form['#cache']['tags'] : [],  $config->getCacheTags());
    

    This too.

  6. +++ b/core/modules/search/src/Controller/SearchController.php
    @@ -89,7 +90,9 @@ public function view(Request $request, SearchPageInterface $entity) {
             // Log the search.
    -        if ($this->config('search.settings')->get('logging')) {
    +        $config = $this->config('search.settings');
    +        $build['#cache']['tags'] = Cache::mergeTags(isset($build['#cache']['tags']) ? $build['#cache']['tags'] : [],  $config->getCacheTags());
    +        if ($config->get('logging')) {
               $this->logger->notice('Searched %type for %keys.', array('%keys' => $keys, '%type' => $entity->label()));
             }
    

    Note that the configuration here does not affect the output, only if we log or not, so not relevant for the render cache.

  7. +++ b/core/modules/taxonomy/src/TermForm.php
    @@ -88,6 +90,8 @@ public function form(array $form, FormStateInterface $form_state) {
           '#value' => $term->id(),
         );
     
    +    $form['#cache']['tags'] = Cache::mergeTags(isset($form['#cache']['tags']) ? $form['#cache']['tags'] : [],  $config->getCacheTags());
    +
    

    Same for the term form, then?

  8. +++ b/core/modules/user/src/AccountForm.php
    @@ -74,6 +74,7 @@ public function form(array $form, FormStateInterface $form_state) {
         $user = $this->currentUser();
         $config = \Drupal::config('user.settings');
    +    $form['#cache']['tags'] = $config->getCacheTags();
    

    This is also an entity form.

  9. +++ b/core/modules/user/src/Form/UserCancelForm.php
    @@ -76,6 +77,7 @@ public function getConfirmText() {
         $user = $this->currentUser();
         $this->cancelMethods = user_cancel_methods();
    +    $config = $this->config('user.settings');
    

    This too

=> There won't be much left, which is fine :)

borisson_’s picture

I kept the changes in CommentDefaultFormatterCacheTagsTest, removed all other changes.

Wim Leers’s picture

FileSize
12 KB
3.51 KB
  1. +++ b/core/modules/aggregator/src/Controller/AggregatorController.php
    @@ -173,6 +173,7 @@ public function adminOverview() {
         $build = $this->buildPageList($items);
    +
         $build['#attached']['feed'][] = array('aggregator/rss', $this->config('system.site')->get('name') . ' ' . $this->t('aggregator'));
    

    Whitespace-only change, should be reverted.

  2. +++ b/core/modules/user/src/Form/UserPasswordResetForm.php
    index 7cc10be..76d26fc 100644
    --- a/sites/default/default.settings.php
    
    --- a/sites/default/default.settings.php
    +++ b/sites/default/default.settings.php
    

    The changes here are unintentional.

  3. +++ b/core/modules/user/src/Form/UserLoginForm.php
    index 69b4588..303a21e 100644
    --- a/core/modules/user/src/Form/UserPasswordResetForm.php
    
    --- a/core/modules/user/src/Form/UserPasswordResetForm.php
    +++ b/core/modules/user/src/Form/UserPasswordResetForm.php
    
    +++ b/core/modules/user/src/Form/UserPasswordResetForm.php
    +++ b/core/modules/user/src/Form/UserPasswordResetForm.php
    @@ -93,6 +93,8 @@ public function buildForm(array $form, FormStateInterface $form_state, AccountIn
    
    @@ -93,6 +93,8 @@ public function buildForm(array $form, FormStateInterface $form_state, AccountIn
           '#type' => 'submit',
           '#value' => $this->t('Log in'),
         );
    +
    +    $form['#cache']['tags'] = $this->config('user.settings')->getCacheTags();
    

    Turns out this is basically the "one time login form", hence I failed when trying to write a test for it. This is *never* cached. So can be removed.

  4. AccountForm was removed as per #26.8, but that's wrong: it's also visible to the end user at user/register.
Wim Leers’s picture

Issue tags: +Needs tests

What this now really needs, is tests.

Status: Needs review » Needs work

The last submitted patch, 28: wherever_simple_config-2407765-28.patch, failed testing.

Wim Leers’s picture

Status: Needs work » Needs review
FileSize
11.94 KB

#2403485: Complete conversion of comment form validation to entity validation, committed 5 minutes before #28, conflicted with #28. Straight reroll.

Berdir’s picture

Status: Needs review » Needs work

Needs work for tests then.

Wim Leers’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
FileSize
16.9 KB
5.6 KB

Below, a note for every single file touched in this patch, to ensure we don't miss any test coverage.

  1. --- a/core/modules/book/src/BookManager.php
    +++ b/core/modules/book/src/BookManager.php
    

    Added test for this one in BookTest.

  2. +++ b/core/modules/book/src/BookManager.php
    --- a/core/modules/comment/src/CommentForm.php
    +++ b/core/modules/comment/src/CommentForm.php
    

    Added test for this one in CommentAnonymousTest.

  3. +++ b/core/modules/comment/src/CommentForm.php
    --- a/core/modules/comment/src/CommentViewBuilder.php
    +++ b/core/modules/comment/src/CommentViewBuilder.php
    
    +++ b/core/modules/comment/src/CommentViewBuilder.php
    --- a/core/modules/comment/src/Tests/CommentDefaultFormatterCacheTagsTest.php
    +++ b/core/modules/comment/src/Tests/CommentDefaultFormatterCacheTagsTest.php
    

    Test coverage: done.

  4. +++ b/core/modules/comment/src/Tests/CommentDefaultFormatterCacheTagsTest.php
    --- a/core/modules/contact/src/Controller/ContactController.php
    +++ b/core/modules/contact/src/Controller/ContactController.php
    

    Added test for this one in ContactSitewideTest.

  5. +++ b/core/modules/contact/src/Controller/ContactController.php
    --- a/core/modules/forum/src/Controller/ForumController.php
    +++ b/core/modules/forum/src/Controller/ForumController.php
    

    Added test for this one in ForumTest.

  6. +++ b/core/modules/forum/src/Controller/ForumController.php
    --- a/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php
    +++ b/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php
    
    +++ b/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php
    +++ b/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php
    @@ -93,6 +93,7 @@ function testPageCacheTags() {
    
    @@ -93,6 +93,7 @@ function testPageCacheTags() {
           'config:system.menu.tools',
           'config:system.menu.footer',
           'config:system.menu.main',
    +      'config:system.site',
         ));
     
         // Full node page 2.
    @@ -124,6 +125,7 @@ function testPageCacheTags() {
    
    @@ -124,6 +125,7 @@ function testPageCacheTags() {
           'config:system.menu.tools',
           'config:system.menu.footer',
           'config:system.menu.main',
    +      'config:system.site',
    

    We show the login block to anonymous users by default, hence this is indirect test coverage for UserLoginForm.

  7. +++ b/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php
    --- a/core/modules/user/src/AccountForm.php
    +++ b/core/modules/user/src/AccountForm.php
    

    Added test for this one in UserRegistrationTest.

  8. +++ b/core/modules/user/src/AccountForm.php
    --- a/core/modules/user/src/Form/UserLoginForm.php
    +++ b/core/modules/user/src/Form/UserLoginForm.php
    

    Added test for this one in UserLoginTest.

  9. +++ b/core/modules/user/src/Form/UserLoginForm.php
    index 69b4588..f645abb 100644
    --- a/core/modules/user/src/Form/UserPasswordResetForm.php
    
    --- a/core/modules/user/src/Form/UserPasswordResetForm.php
    +++ b/core/modules/user/src/Form/UserPasswordResetForm.php
    
    +++ b/core/modules/user/src/Form/UserPasswordResetForm.php
    +++ b/core/modules/user/src/Form/UserPasswordResetForm.php
    @@ -93,6 +93,7 @@ public function buildForm(array $form, FormStateInterface $form_state, AccountIn
    
    @@ -93,6 +93,7 @@ public function buildForm(array $form, FormStateInterface $form_state, AccountIn
           '#type' => 'submit',
           '#value' => $this->t('Log in'),
         );
    +
         return $form;
       }
     
    

    Removed this now useless hunk.

dawehner’s picture

It still feels wrong to have a getCacheTags method on ConfigBase, but well, we decided to go the couple everything route.

  1. +++ b/core/modules/user/src/Form/UserPasswordResetForm.php
    @@ -97,7 +97,7 @@ public function buildForm(array $form, FormStateInterface $form_state, AccountIn
    -   * {@inheritdoc}
    +   * {@inheritdoc}o
    

    ooh ooh ooh

  2. +++ b/core/modules/user/src/Tests/UserLoginTest.php
    @@ -16,6 +16,16 @@
    +    $this->drupalGet('user/login');
    +    $cache_tags = explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Tags'));
    +    $this->assertTrue(in_array('config:system.site', $cache_tags));
    
    +++ b/core/modules/user/src/Tests/UserRegistrationTest.php
    @@ -24,6 +24,15 @@ class UserRegistrationTest extends WebTestBase {
    +  function testCacheTags() {
    +    $this->drupalGet('user/register');
    +    $cache_tags = explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Tags'));
    +    $this->assertTrue(in_array('config:user.settings', $cache_tags));
    

    It would be nice to have a one line comment why we expect it to be there. Its not obvious, really.

Wim Leers’s picture

Status: Needs review » Needs work
Wim Leers’s picture

Status: Needs work » Needs review
FileSize
16.9 KB
1.38 KB

Addressed both points in #35.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Thank you for addressing my feedback.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

Shouldn't we be adding the system.site cache tag to SystemBrandingBlock::getCacheTags()?

+++ b/core/modules/user/src/Form/UserPasswordResetForm.php
@@ -97,7 +97,7 @@ public function buildForm(array $form, FormStateInterface $form_state, AccountIn
-   * {@inheritdoc}
+   * {@inheritdoc}o

It looks like the patch in #37 does not contain the changes that the interdiff says it does.

Wim Leers’s picture

Status: Needs work » Needs review
FileSize
18.44 KB
20.82 KB
5.78 KB

Indeed, I uploaded the same patch as before :/ Stupid — sorry!

And indeed, that cache tag should be added there. Great catch.

Wim Leers’s picture

From IRC:

berdir: WimLeers: I thought we killed theme_global_setting ?
WimLeers: berdir: actually yeah I thought that too :P
WimLeers:good point
WimLeers:let me check
WimLeers:#multitasking = gaaaah
berdir: there is only one usage of it ;)
WimLeers: there we go
WimLeers: lol
WimLeers: Wim-- for not noticing

Wim Leers’s picture

FileSize
20.72 KB

Testbot--

Berdir’s picture

Status: Needs review » Reviewed & tested by the community

Last few interdiffs look good, verified that those changes are actually in the patch ;)

Back to RTBC.

Fabianx’s picture

RTBC + 1

amateescu’s picture

  1. +++ b/core/modules/book/src/BookManager.php
    @@ -352,6 +353,7 @@ protected function addParentSelectFormElements(array $book_link) {
    +    $form['#cache']['tags'] = Cache::mergeTags(isset($form['#cache']['tags']) ? $form['#cache']['tags'] : [],  $config->getCacheTags());
    

    This mergeTags() with ternary logic as an argument is used a lot and it's quite cumbersome to write, how about adding a Cache::mergeRenderArrayTags() (or similar) that receives a render array and does all the isset logic for you?

    It could even receive the render array by reference to make it even shorter to write.

  2. +++ b/core/modules/book/src/Tests/BookTest.php
    @@ -77,6 +77,17 @@ protected function setUp() {
    +  function testCacheTags() {
    

    A lot of these new test methods are added in web tests so they're doing a full Drupal install just for a single assertion. That's.. not very nice of them :)

  3. +++ b/core/modules/book/src/Tests/BookTest.php
    @@ -77,6 +77,17 @@ protected function setUp() {
    +    $this->drupalGet('node/add/book');
    +    $cache_tags = explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Tags'));
    +    $this->assertTrue(in_array('config:book.settings', $cache_tags));
    

    This logic is also repeated a lot, how about introducing a method on the base test classes for it? It could receive the cache tag as the first argument and an optional path or Url object for the drupalGet() part.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

re #46.1 I agree a method here would be helpful - I don't think the render array should be passed in by reference though.
re #46.2 but are there obvious places to add this?
re #46.3 yep maybe an assertCacheTag method on WebTestBase

Wim Leers’s picture

Status: Needs work » Needs review
FileSize
20.48 KB
8.02 KB
  1. Addressing in next comment, because it's not clear yet what the best way to do it is. That keeps this interdiff clearer.
  2. I agree. But like #47.2, I don't see any better place to add them.
  3. Agreed, done. Did exactly what #47.3 suggested.
Wim Leers’s picture

So, regarding #46.1 & #47.1: I agree in principle with #47, but OTOH I wonder if it's problematic to be copying potentially huge render arrays? I think it might actually be better in this case to work by reference because of that.

Also: if we add a method to do this for cache tags, we also want to do it for cache contexts.

So, in this first attempt, I'm adding a method that does work by reference. Looking forward to your feedback :)


But while working on that approach (let's call the above option A), I thought of another (let's call it option B), which I think is actually better, because it doesn't force us to add another method per type of bubbleable metadata.

Once #2429257: Bubble cache contexts lands (currently RTBC), it'd then allow us to easily absorb the cacheability metadata from cacheable objects (objects that implement CacheableInterface) and apply it to a render array. Even when more cacheability metadata is added to the render system in the future (like max-age and min-age), code won't have to change.

Status: Needs review » Needs work

The last submitted patch, 49: wherever_simple_config-2407765-49_option_b.patch, failed testing.

Fabianx’s picture

I agree with #49, but I am 100% for option B).

The reason being, that those are internal properties that no user of render arrays or CacheableInterface should know about.

amateescu’s picture

About #46.2, I don't know... any existing method in those test classes? :P

And #49 option B looks great.

Wim Leers’s picture

Status: Needs work » Needs review

Glad to see the agreement for #49 option b :)

Oops, config objects don't implement CacheableInterface, it's just that ConfigBase has a getCacheTags() method. (Neither do entities, there it is similarly just the EntityInterface that has a getCacheTags() method.)
(See the relevant CR: https://www.drupal.org/node/2406455.)

So… that actually raises the interesting point… that in fact we do want config objects as well as entities to implement CacheableInterface, because that was always intended to be the sole generic interface to implement. But doing that here would probably be out of scope for this issue.

Therefore I wonder if it wouldn't be better to address #46.1 using #49 option b in a follow-up issue?

Fabianx’s picture

Agree, but we should probably then not introduce a new option a) in between, lets create the follow-up and back to RTBC for the original patch?

Wim Leers’s picture

amateescu’s picture

FileSize
6.94 KB

Here's an interdiff for #46.2, feel free to apply or discard it if you don't like it :)

Otherwise, RTBC++.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

I like #56 - let's do it. amateescu++

Wim Leers’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
20.9 KB

This must be the easiest patch I ever rolled.

git apply 48.patch
git add --all core
git apply interdiff.txt
git diff HEAD > 58.patch

Thanks, @amateescu :)

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.0.x, thanks!

  • catch committed 468646e on 8.0.x
    Issue #2407765 by Wim Leers, borisson_: Wherever simple config is used...
Wim Leers’s picture

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.