A very common paradigm is to want type-specific verticals and behaviors. CCK, taxonomy, books and others can add facets that are type-specific. This patch adds a checkbox to each facet block configuration form asking if the block should be type dependent. If checked, the facet block only shows if the type:book or type:story filter is selected first. This is very convenient for our new in-the-well browsing facets. It also lets you enable lots and lots of facet blocks and not worry about running out of real estate because a large number of the blocks can be type dependent and only show when the requisite type filter has been selected. Committing the attached patch. Will leave open for review for some time.

Comments

robertdouglass’s picture

StatusFileSize
new6.99 KB
robertdouglass’s picture

Status: Needs review » Fixed
robertdouglass’s picture

StatusFileSize
new3.57 KB

A followup that factors the visibility logic into a new function in the apachesolr.module for reusability. Committing attached patch.

robertdouglass’s picture

StatusFileSize
new1.24 KB

Followup bug fix: $module was hardcoded.

Status: Fixed » Closed (fixed)

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

socki’s picture

StatusFileSize
new6.06 KB

Here is a consolidated patch file which packages together all three of the above fixes into a single patch. This has been tested against the 6.x-1.x RC3 version of the module.

SergeyR’s picture

Status: Closed (fixed) » Active

the one aspect leaved to be solved
if you uncheck type facet -it's good other depended facets filters automatically to be unchecked
i.e. if you switch your searching from "news" to "products" -filters by "type of news" is become useless -and more.. you cannot uncheck it cause this block become unvisible. Crazy situation )))

the another thing- to expand idea of "type dependent facet blocks" to "any previous filter choiced facet block"
i.e. the only subset of objects has some kind of feature -i don't want to see this feature untill appropriate filter of that subset is choosed.

PS just found bad example from whitehouse.gov

1. I dont like to see "Filter by Blog Category" untill "Blog post" from "Filter by type" checked
2. I dont like "White house" be checked as "Blog Category" , as soon as i unchecked "Blog post" as "Type"

pwolanin’s picture

Version: 6.x-2.x-dev » 7.x-1.x-dev
pwolanin’s picture

Project: Apache Solr Search » Facet API

moving to Facet API queue for future consideration.

cpliakas’s picture

Category: feature » task

This seems very possible, and not that difficult to implement once we finish the task at #1147510: Rework logic to initialize all facet builds earlier in the application flow. Ideally there should be a hook that prevents the facet from rendering so other projects can add conditions such i.e. "only render this facet if content type x is active".

If we take a look at the FacetapiAdapter::addFacetsFilters() function, it would be simple to invoke the hook to allow modules to prevent the query type plugins from firing. That way the backend won't process the data. On the rendering side, we would have to take a cached return value from the hook and prevent the facet from rendering in FacetapiAdapter::buildRealm().

Switching to a task, because I think this is important.

Anonymous’s picture

Looking forward to this as apachesolr module is now dependent on the facetapi so I've lost the ability to easily control block visibility according to type.

For the moment, I'm just using some PHP code in my block visibility settings:

<?php
  if (strpos($_SERVER["REQUEST_URI"], 'bundle%3Amycontenttypename')) {
    return TRUE;  // block will be shown
  }
  return FALSE;
?>
pwolanin’s picture

So a discussion Chris and I has was whether this should be generic functionality (a block can depend for visibility on any filter being active) or focus just on the content type use case.

Making a generic version is going to be harder to have a comprehensible UI.

cpliakas’s picture

I think it would be simple to make the framework for the functionality generic, however the implementations would have to be aware of the field they are dependent on. I cannot think of a non Content Type implementation off the top of my head, but the framework should be generic enough to at least support other use cases.

pwolanin’s picture

Does this affect the facet fetching or only rendering code?

The prior apachesolr implementation had this sort of comment:

 // Checking the block visibility saves us from adding facet fields to the query
 // which won't be used.
 if (apachesolr_block_visibility($query, $module, $delta)) {

So, I think the corresponding effect would be in the execute() method of the FacetapiQueryType plugin there would have to be some way to get from the global (not realm) settings all the facets that have to be active in order for execute() to add the facet params? Not sure how to get a facet just by name. Is this functionality specific to the block realm?

Looking in the code, there is a comment about facetapi_enabled_facets_get() on line 265 of the module, but I don't see that it exists.

Perhaps add a drupal_static() to facetapi_get_facet_info() so we can call it repeatedly?

cpliakas’s picture

My goal is to abstract the process so the modules can implement something like a hook_facetapi_suppress_facet() which will simply prevent the query type plugin from being added in FacetapiAdapter::addActiveFilters (hence one of the reasons why #1147510: Rework logic to initialize all facet builds earlier in the application flow was helpful) . If no query type plugin is added, this takes care of both the params set in the backend and the display of the facet. I think I have to modify the flow slightly in the FacetapiFacetProcessor::__construct() method to skip the initialization routines if the facet doesn't have a query type plugin, but the code is pretty close as it is.

In short, the facet will still be enabled, but the backend won't fetch facet data nor will the rendering mechanism display the facet.

cpliakas’s picture

As a side note, setting it up this way allows for extensibility for contributed modules to add whatever dependency logic they want. Toying with the idea of not having the type dependency in Facet API and separating it out to another module.

cpliakas’s picture

So just a note here, after playing around with this for an hour on the train, I settled on a system that works really well. I am ditching the idea of implementing a hook as well as the idea of separating this functionality out into another module. The concept of dependency plugins works extremely well and allows developers to add whatever dependency logic they need. Core Facet API will come with two dependency plugins, content type and role. This way you can have a dependency on the active content type, and you can even have a dependency to say "only users with this role can use this facet.".

The additional benefit of this approach is if the dependencies aren't met then the server doesn't even process that facet. Therefore this does more than just hide the data. I set up the dependency-551620 feature branch to develop this functionality since it is a larger change.

pwolanin’s picture

Sounds like good progress.

cpliakas’s picture

StatusFileSize
new158.1 KB

Development is progressing well, and the plugin system seems to be the right way to solve this. Attached is a screenshot of where we are at now. Any facet that has one or more dependency plugins associated with it will have a new configuration form to edit the dependencies. Each plugin can provide settings that are usually contained in a vertical tab. This will allow for multiple plugins to be chained together in a scalable way from the UI perspective.

pwolanin’s picture

Took me a second to grasp the middle radio's text, but that right there probably solves 90% of use cases, especially since in D7 taxonomy term reference is a field too.

cpliakas’s picture

Status: Active » Fixed

Marking as fixed, although that second option you mention is not implemented yet. The reason we need the facet definition to have the field information in order to see what bundles reference it. The dependency system has been merged back into the 7.x-1.x branch, and the two remaining issues are listed below:

#1158592: Add an update function to avoid undefined index errors from dependency system
#1158594: Implement the "referenced" dependency setting

Status: Fixed » Closed (fixed)

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

SergeyR’s picture

please look at endeca "precedence rules"
as i understood this is a possibility to manage facet dependencies in general case
and in fact the actual dependencies pligins are just limited to parenth's facet that is content type
my vision -it must something like this:
"at least one of the selected content type must be active" >>>"all selected filters type must be active"
or
"all selected value of filters type must be active"

second approach just eliminate queries to search server with possible zero count facets -but hard for configuration interface -anyway first approach is working-see next:

i.e. -you have content type (read: value of filter1) " news" with field "date" (filter2) and "goods" (another value of filter1) with "manufacturer" (filter3)
and you have idea to select date as soon as news are selected and to select manufacturer as soon as goods are selected
make dependecies filter1>filter2 and filter1>filter3
as soon as you select any value of filter1 -both filter2 and filter3 will be activated -but if value of filter1 will be news -filter2 will work but filter3 will have zero count and appropriate block will be invisible -anyway the goal achieved

PS
sytem must to disactivate children's filters as soon as parenth's filters are disactivated

cpliakas’s picture

Opened a new issue for this at #1218714: Add more advanced filter and dependency settings. Let's continue discussions there.