Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Currently, when you add a facet block, it is shown on every page.
We should add a setting in the UI so you can choose per facet if the facet is shown on all pages or if it's shown only on the pages that display the facet source. The tricky part is that a view can have different modi, and we need to support them all.
#1 Only show block when the page is equal to the views page.
#2 Only show block when the views block will be rendered at the current page.
In this issue, we're also adding the possiblity for views to be rendered in blocks and to have facets built on that facet source.
Comment | File | Size | Author |
---|---|---|---|
#38 | add_show_only_on_a-2598902-38.patch | 12.49 KB | borisson_ |
Comments
Comment #2
borisson_This makes me sad; but it works.
Comment #3
Nick_vhI had a conversation with effulgentsia and he had some very interesting thoughts. Some of them aligned with what we were thinking when talking to each other.
His first thought is the one inline with what we were thinking, iterating over the block list and see if it is present.
His second thought is, in my opinion, way nicer.
If we can pass the block as a context object to our facet block, we can call that function and directly see if we need to show it or not. This allows us to execute this at runtime and does not require a whole lot of coding. We can have similar mechanisms in place for other types of view modes, if they exists. When we get to a PanelViewFacetSourceManager and hence, the generated plugins from them, we can figure out how panels discovered how to show a certain view and act on it.
Hopefully that helps us a bit further?
Comment #4
Nick_vhComment #5
Nick_vhWe solved the problem of the views page (See borisson_'s patch) but we still need work in figuring out if the view, in block modus, will be rendered somewhere on the page. For this, we need to send the views block as a context object. This might not be as hard as it sounds. We already pass the view along, so we could most likely also send the $block->access('view') method?
Comment #6
StryKaizer@borisson_: the code in #2 will always trigger when the current page is a page view (e.g. frontpage)
If you have a search-index in a block, it will always be hidden because of this.
We need to find out first if the current facet has a page view as facetsource, and only then trigger your code.
Comment #7
StryKaizerAttached is a reworked version from #2 where I moved the logic into the datasource (as this should be implemented by the datasource plugin instead of on a global level)
I also refactored the facet interface a bit, making getDataSource return an instance of the datasource plugin.
If you only need the datasource id, you can still do getDataSourceId().
I looked into the Blocks module for this, and they seem to do it like that too.
Remarks from #6 are not addressed yet, but can now live in the datasource plugin.
Comment #8
borisson_Fixed a couple of small nitpicks in the patch.
@Nick_vh explained some things to me and I think I might understand where we should be going with this.
We should split up the functionality for pages and blocks into different facet sources. The current facetSource should be renamed to a base class (
SearchApiViewsDeriverBase
) and there should be 2 classes implementing that.SearchApiViewsPageDeriver
andSearchApiViewsBlockDeriver
. Those 2 new classes should each implement::isBeingRendered
, that way we can split up the support for blocks to a followup.Getting in page support for views can be based upon this patch.
I'm not sure about
::isBeingRendered
as a method name though, I suggest::isRenderedInCurrentRequest
as a more verbose option.Comment #9
StryKaizerYup, that sounds like a good idea!
isRenderedInCurrentRequest sounds good.
Comment #10
borisson_What I explained in #8 I did in the attached patch. Still need to rename that method though, coming up.
Comment #11
borisson_As promised in #10.
Comment #12
borisson_Renamed the facet_source to facet_source_id in the schema and integration test as well.
Comment #13
StryKaizerWIP
Started from #8 + #12
Current patch is not rendering results anymore atm. I renamed the search_api_view id to search_api_views_page to make the plugin system use the correct plugin.
Comment #14
borisson_The reason nothing rendered anymore is because this needs a patch to search api. This feels wrong but it makes results appear again.
Comment #15
borisson_Updated the patch in #13, added a config setting and changed the UI / FacetEntity en FacetInterface to make sure that is not just a hardcoded value but that this is actually something that can be configured.
Comment #16
StryKaizer#15 with a bit of variable/documentation changes attached
Comment #19
Wim LeersSo, this is a quite interesting problem. Because blocks in theory are meant to be independent of the other blocks on the page. Otherwise you can't render them independently, in parallel or via ESI.
I think I agree part of the solution is to have this "Facet-for-Views-block"-block require a "Views block" Context. But… that would mean that the Views block must expose/emit another context. Which is where we enter a catch-22, enforced by the earlier mentioned requirement that blocks can be rendered independently: the visible blocks are determined by loading all the contexts, and then checking if the visibility conditions are met (see
\Drupal\block\BlockAccessControlHandler::checkAccess()
). I think it's not possible for that set of run-time contexts to change during a request (i.e. before the Views block is rendered, this "views block is visible" context would be FALSE, and after it is rendered, it'd be TRUE), because then execution order matters, and hence parallelism is broken.I think you need @eclipsegc and @tim.plunkett's input here.
Comment #20
Nick_vhWhat I *think* we should do is the following. We add support for having a facetsource from a block that was created by views (so not the display mode). Because this block then becomes the facet source, we can pass it as context. We can then execute a $block->access() check to see if the block where the view is in would be shown and if not, we stop rendering the facet and in effect we also don't try to execute the view to get our results. We can then continue to execute our empty behavior for the facet block or whatever we like with this state. Most likely we will need to use the exact same approach when we want to add support for panel pane's with any kind of search api view in it. The pane will be the facet source, not what is in it.
Current facet_source plugins:
New facet_source plugins:
It would create a facet source for every block defined in the blocks structure that is part of a Search Api Views object that has the block display mode.
Some remarks from @wimleers:
Just be aware then that it's possible to have different "empty" behavior for the Views block and the Facet block: it's possible to hide the Views block and have the Facet block say "no facets available", which may be confusing. I think you may want to have some `hook_requirements()` checks that does sanity checks in those areas to prevent those kinds of misconfigurations.
(or at least warn people)
For reference I include the full conversation with Wim.
Comment #21
Nick_vhWe could, to avoid the requirements issue (where empty behavior of a view is doing different things compared to an empty facet) execute the block as a whole. The view will be cached and we will need to execute the view anyway to get the results of the search. We are already executing the view when the facet_source is a SearchApiViewsPage, so this is not too different compared to the block.
Thoughts?
Comment #22
borisson_Attached patch adds block as a facet source in the backend, haven't tested it yet on the frontend but this is a start.
Comment #23
borisson_Attached patch has some more work put into it, but still doesn't work.
For some reason
$facet_results = $results->getExtraData('search_api_facets');
in::fillFacetsWithResults
doesn't return any data.When tracing this back to
\Drupal\search_api_db\Plugin\search_api\backend\Database::search
it seems that the call to$query->getOption('search_api_facets')
returnsnull
.Comment #24
borisson_Code cleanup + getting it to work.
Comment #25
borisson_Comment #26
borisson_This needed a reroll.
Comment #28
marthinal CreditAttribution: marthinal commentedWith the 'show only on a page that contains the facet source' option selected, facet blocks appear on multiple pages and not only when the facet source is visible. Fixed with my last patch + added integration tests.
Comment #29
borisson_I reviewed my own patch. These remarks need to be resolved and then I'll be happy with the result.
As mentioned in yesterdays facetapi call, I'm very unhappy with this solution even though it works.
This works but doesn't look very elegant.
bogus empty line should be removed from patch.
2 periods and the wording isn't correct (views blocks)
This is currently the same implementation as the one for views pages (and that one was not correct).
This needs more work.
This is currently duplicated in every derivative; this could move to #2603572: Create a SearchApiBaseFacetSource class., I think
Comment #30
Wim LeersI'm confused now. What did #27/#28 do, if this issue is still open?
Comment #31
borisson_@Wim Leers: in this issue, we've done work on 2 separate but related issues:
1. Add a new facet source:
BlockSearchApiViewsBlock
2. Make sure the 'show only on a page that contains the facet source' checkbox works.
#27 did the work for search api views that have a page display. That's a different facet source and needs another implementation of
::isRenderedInCurrentRequest
.Comment #32
borisson_- Moved #29.6 to #2603572: Create a SearchApiBaseFacetSource class.
- Fixed #29.3, .4, .5.
We still need to address #29.1 and #29.2 but I feel like those can be fixed in a followup.
Comment #34
marthinal CreditAttribution: marthinal commentedI've detected that if the 'display_id' is the same for 2 different views (I can reproduce with different backends or indexes for example) the facets will be visible in both views. To reproduce you can create 2 indexes with the same display id by default. Then you add 1 facet per facet source. Both views will display 2 facets.
This is fixed in my last patch
Comment #35
borisson_With #2608004: Add a base class for facet source derivers and #2603572: Create a SearchApiBaseFacetSource class. in, this reroll makes this patch somewhat smaller; hurray.
Comment #36
StryKaizerneeds reroll
Comment #37
borisson_Comment #38
borisson_Needed a reroll because of module name change.
Comment #39
borisson_We should probably split of the remaining work into a new issue if someone is still interested in this. For now we should probably not include views blocks yet.