When a user visits a certain page I want to hide a certain facet block and also force it to have a certain value. Hiding the block is easy enough with block visibility settings. But Is it possible to force the facet to be have a certain value (so that dependent facets show up) without resorting to redirecting the user to an ugly url with query string?
In other words, I want the user to be able to go to:
http://www.mywebsite.com/browse/assets
And get facets to display as if they were at:
http://www.mywebsite.com/browse/assets/?f[0]=bundle%3Aasset
I'm aware that I can force the bundle facet by creating a new apache solr search page with custom filter (bundle:asset), and this works to restrict results, but it does not automatically set the value of the facet api block, so dependent facet blocks are not triggered as I want them to be.
Comment | File | Size | Author |
---|---|---|---|
#3 | facetapi-1715202-3.jpg | 66.69 KB | cpliakas |
Comments
Comment #1
cpliakas CreditAttribution: cpliakas commentedHi JordanMagnuson.
Thanks for the post. My recommendation would actually be to use the search page with a custom filter and then build a dependency plugin to match your condition for three reasons. The first is that it will be tricky to do what you are trying to accomplish with Facet API, and the second is that it will take more processing in that facets are much more expensive than straight filters, and Facet API will also have to re-process the active items. The third reason is that the value is still going to show up in the breadcrumbs, so you are going to have to code your way around that.
With that being said, I am thinking that the easiest way to do what you are asking is to execute the following snippet somewhere before the facets are rendered. Effectively you will alter the facet "parameters" containing the filters to do what you are trying to accomplish.
The code above might be off because I didn't validate it, but play around and see if that works.
Thanks,
Chris
Comment #2
JordanMagnuson CreditAttribution: JordanMagnuson commentedThanks much for your reply Chris--I really appreciate it! I'd definitely like to go with whatever solution you think would be best/most performant.
I've got the solr search page with the custom filter, which works to limit results, so the issue then is just how to go about creating a dependency plugin that suits my needs for the given facet block. If you could help point me in the right direction, I'd be extremely grateful.
Let me explain my situation just a little bit further. I've got three solr search pages:
So the "issue" is with the two dependent facet blocks, "type of template" and "type of asset". These show up on the search page when their dependencies are triggered--which is what I want--but they don't show up on the "Browse" pages. It seems the dependency I need for these blocks is somewhat complex: I want them to show up in two different situations (either/or): show if a bundle this field is attached to is active (on the main search page) OR show if I am on the "Browse Assets" page (or "Browse Templates" page for the "type of template" block).
Have I described the situation clearly enough? Do you think it would be easy enough to write a dependency plugin to get at what I'm after?
Comment #3
cpliakas CreditAttribution: cpliakas commentedHm, cool use case. I think this is a great opportunity to show how to build a dependency plugin, so I am going to post some code that you can probably start with and run from there. Just to give some transparency about the dependency plugin system, generally how it works is that the dependencies are satisfied if at least one of the conditions pass. So you can definitely add multiple dependencies to that facet (i.e. content type facet selected or custom filter active) and it will have the either / or effect you are looking for. We already have the content type dependency as you alluded to, so what we are going to do is build a simple dependency plugin to check if a filter is set.
The first thing we are going to do is register our dependency plugin using hook_facetapi_dependencies(), which points to a class containing our dependency plugin.
The next thing we are going to do is register the plugin for the facets that we want this dependency to work for by implementing hook_facetapi_facet_info_alter(). This example uses the "bundle" facet, but it could be any facet or combination of facets that you want.
Last, we are going to actually write the plugin class. It will be an extension of the abstract class FacetapiDependency, and make sure to put it in Drupal's class registry so it can be autoloaded. See the "files" section. We will override the settingsForm() and getDefaultSettings() methods to define the UI, and we will implement the execute() method to execute the plugin.
If all went well, you will be able to configure your dependency. Simply add the filter you are checking for in the text field, and it will be required for the dependency to pass.
The match in the execute() method will have to be more sophisticated to work for complex use cases, but you get the idea :-).
Good luck,
Chris
Comment #4
JordanMagnuson CreditAttribution: JordanMagnuson commentedWow, Chris, thanks so much for your help! I have a much better idea of how dependencies work now, and was able to get things working perfectly thanks to your invaluable code examples. I love solr and facet api! Between the two I've managed to replace most of my views-based pages with super-fast solr-based pages.
I did find I needed to modify a couple little bits of the plugin code you provided. Let me know if these corrections look right to you:
The code below just seems to get the id of the first solr page returned, rather than the current page?
Replaced with:
The code below seemed to create an AND type of situation where this dependency had to be met in addition to any others, rather than the OR type situation I was looking for:
I just flipped the return logic around, and this seems to work as desired:
Comment #5
cpliakas CreditAttribution: cpliakas commentedJordanMagnuson, thanks for posting your updates! I think that as long as the code works as expected, then run with it.
The reason why my code checked for the first search page (which I agree is hacky) is because there are some instances where there will be a "%" in the path and it therefore won't match the
current_path()
. If your pages don't have a %, then your code will work fine. I am wondering if there is some middle ground to solve this use case more reliably, but that is a whole other topic :-)Anyways, great work, and thanks for posting back.
Chris
Comment #6
cpliakas CreditAttribution: cpliakas commentedTo follow up, you are right, my code is borked. It breaks under certain conditions. As a workaround, I came up with another snippet that I am using in another module. See the apachesolr_stats_get_page_id() function.
Comment #7
JordanMagnuson CreditAttribution: JordanMagnuson commentedThanks for the followup, Chris.
Comment #8.0
(not verified) CreditAttribution: commentedAdded last paragraph.
Comment #9
JordanMagnuson CreditAttribution: JordanMagnuson commentedI've run into another use case for which the above solution does not work.
The situation is this:
I have a site with a bunch of nodes and a boolean field called "patrons_only," which marks items that are only available to members with "patron" status.
I have a default browse page that allows users to browse all nodes on the site via an Apache Solr page, with facet filtering provided via Facet API.
By default, patron_only items are not shown, but I want to allow users to include patron_only items in results via a filter like so:
[ ] Show Patron items
The single checkbox filter can be achieved fairly easily via rewriting, but behind the scenes we have two values with an OR filter:
With the option for the user to select:
It's easy to show all of the items, and then allow the user to filter, but the problem is that I want the default display to hide the patron_only items (so I want patron_only:false to be selected). If I set this up via a default solr filter on that page (bm_patron_only:false) then there's no way to later display those items via facet api filter... So once again, I want to force the facet api filter into a default start state for the given page, but find myself unable to do so...
Any thoughts on how best to achieve what I'm after?