I ran into the problem that facets do not work on views with caching enabled. Looking at the issue queue, I'm not the only one. The README clearly mentions that caching should be disabled (even though two lines halfway a 125-line file are easily missed) but I think the Facets module could actively warn users when configuring facets.
Proposed solution
When saving a facet configuration form (eg. /admin/config/search/facets/[facet]/edit or /admin/config/search/facets/[facet]/settings), check if the source is a view, load the view config, and check if caching is disabled. If not, produce a warning with drupal_set_message.
Comments
Comment #2
borisson_Proposed resolution sounds like a good way to resolve this. It will reduce the issues in the queue, so that'd be great. We'd have to load the correct display for the view as well, but that shouldn't be a problem.
Comment #3
marcvangendLooking at this some more, it seems that someone has already tried to solve this problem. Check out this code starting at line 313 of FacetSettingsForm::submitForm() :
If I'm not mistaken, this code should automatically disable the caching of the view when a facet settings form is saved. Unfortunately it doesn't work because the
$facet_source_idhas a different format than the module expects. When testing this, the facet source ID didn't look like[type]:[view_id]:[display], but like [module]:[type]__[view_id]__[display] ("search_api:views_page__search__page_1" in my case). I guess this is an oversight from the time when facets_update_8001() was introduced.I could of course write a patch that changes the assumptions about what a facet source ID looks like, but that would easily break again. Obviously, this code needs tests. Also, it would be nice to have a utility method on the Facet class so we can "ask" the facet about its source view, instead of having to guesstimate it from the $facet_source_id string.
Maintainers, what do you think is the best approach?
Comment #4
borisson_Yeah, I think we should start by writing a test and changing the assumption.
I think it'd make sense to use ['display_id'] from the facet source definition and load the Search Api display
I wrote this from memory, but in theory we should be able to do this, that should make everything more clear and removes the guessing. Does this make sense @marcvangend?
Comment #5
marcvangendChanged the title because this is in fact a regression introduced in #2772745: Search API integration doesn't check/define feature support of backends.
Writing tests isn't really my forte, especially when it comes to modules I don't fully understand... But thanks to the guidance in comment #4 I did manage to fix the regression. Patch attached, but tests are still needed.
Comment #6
marcvangendI just noticed that the exact same problem occurs in
FacetsSummarySettingsForm::submitForm(), so if the fix from #5 works, we'll have to apply it there too. (Or... do we take code duplication as a hint, and learn that this logic should be implemented in the ViewsPageDisplay class?)Comment #7
borisson_No worries, I enjoy writing tests, I'll give it a go.
Comment #8
borisson_Adds an integration test to check this, I think this should be sufficient. Do you agree @marcvangend?
Comment #9
marcvangendThat looks great, you even tested the message. Now we have to address comment #6.
Comment #10
borisson_I agree with comment #6, but I also think that we can do that as a follow-up. I opened up #2860393: API break: Add getViewsDisplay method to the Search API Facet Source
Comment #11
marcvangendFair enough, we shouldn't try to do everything at once. Thanks for the follow-up.
So for now, applying the same fix to FacetsSummarySettingsForm will suffice. Here is a patch that does exactly that.
No test yet, sorry. I did try to port the new test in facets\Functional\IntegrationTest::testViewsCacheDisable() to facets_summary\Functional\IntegrationTest::testViewsCacheDisable(), but I stopped when I found that there is no createFacetSummary() method yet (comparable to createFacet()).
Comment #12
borisson_I'll give the test a go tonight, I'll leave this tab open, thanks for the hard work you put in already!
Comment #13
marcvangendNo problem, it's a good way to learn about the internals of the Facets module, and the time investment is only a fraction of what I get out of it for free :-)
Comment #14
borisson_Adds a test.
Comment #15
marcvangendLooks great. I (re-)read every line and couldn't find a single nitpick. If part of it wasn't my own code, I would RTBC :-)
Comment #17
borisson_Good enough for me, committed and pushed. Thanks again @marcvangend!
Comment #18
slasher13You can't use other FacetSource provider and you can't use it without search_api, too
Why not use this for search_api_views only like before?
Comment #19
borisson_We still do that, we look for the search api display definition AND check for
if (!empty($search_api_display_definition['view_id'])) {}.That does the same thing.
Comment #20
slasher13Yes, but \Drupal::service('plugin.manager.search_api.display') must be defined.
Comment #21
marcvangendI see. So we should wrap that part of the code in an if-statement?
Comment #22
borisson_I guess we could even do
if (!\Drupal::hasService('plugin.manager.search_api.display')) { return; }to make sure that there's no unneeded nesting.Not sure if I have to revert this issue and fix it in one go or if we add a new patch here. I guess adding a new patch and committing on this issue is ok?
Comment #23
marcvangendI don't think we can
return;at that point, we do want thesubmitForm()method to finish its task even if there is no view, right?Comment #24
borisson_Ah, of course, you're right! Looks like I need to do less things at the same time ;)
Comment #25
borisson_So, something like this?
Comment #26
borisson_Committed that.
Comment #28
slasher13Sorry, a few minutes too late.
I think it's better to check the facet source type, because you can have different facet source plugin provider without search_api support, even if search_api is installed.
Maybe adding the tpye to the facet source plugin definition can solve this.
Comment #30
borisson_Yep, committed. Thanks! Sorry for not having enough patience ;)