I'm trying to create a custom facet & widget that are restricted to only working with each other.
- register a custom facet type using hook_facetapi_facet_info() and set 'query types' to array('myquerytype')
- register a custom facet widget using hook_facetapi_widgets() and set 'query types' to array('myquerytype')
However, I are unable to edit the facet display in the admin area: [admin/config/search/facetapi/(realm)/block/(facetname)/edit]
facetapi_facet_display_form()
contains:
$global_settings = $adapter->getFacet($facet)->getSettings()
FacetapiFacet::getSettings()
: calls
FacetapiAdapter::getFacetSettingsGlobal()
: sets a default 'query_type' of 'term'
$form['global']['query_type']
uses $global_settings->settings['query_type']
for the default option regardless of what the facet actually supports.
If the facet doesn't support 'term' then when you try to save the form you get a validation error to this effect.
FacetapiFacet::getSettings() doesn't seem to be intended to be overriden [at least not without creating a new FacetapiAdapter subclass -- I would expect that creating a new query type shouldn't involve overriding the whole backend].
Two workarounds when creating the Query Type dropdown:
[1] change $global_settings->settings['query_type'] to $facet_settings->settings['query_type']. Without fully understanding everything that facetapi is doing internally I'm not convinced that this is actually a proper solution -- what about all other attributes that are read from the global settings and not the facet settings (eg operator)?
[2] Set #access to true regardless of the number of options. In this case, #default is effectively ignored.
In short: it seems impossible to create a facet & widget that does not support 'term' query type.
Comment | File | Size | Author |
---|---|---|---|
#16 | facetapi-global-defaults-followup-1443340-16.patch | 726 bytes | cpliakas |
#13 | facetapi-global-defaults-1443340-12.patch | 1.1 KB | cpliakas |
#11 | 1443340-facet-global-defaults-2.patch | 967 bytes | levialliance |
#6 | 1443340-6.patch | 842 bytes | gnucifer |
#3 | 1443340-3facet-global-defaults-1.patch | 1.07 KB | ohthehugemanatee |
Comments
Comment #1
cpliakas CreditAttribution: cpliakas commentedHi levialliance.
Thanks for posting. I am changing this to a support request, because I can confirm that the conclusion in the bug report isn't correct. Facet API most definitely can have facets and widgets that don't support the "term" query type.
Did you create a query type plugin for "myquerytype" and register it with the adapter you are using? See the apachesolr_facetapi_query_types() function and the associated classes for an example.
Also, are you sure you want to implement a new query type? I'm not sure I understand the desire to have a facet that is only tied to one widget. I can see the flip use case, where a widget is only tied to one facet. I just discovered that this isn't documented in facetapi.api.php :-(, but there is a "requirements" key that you can use in the widget definition for this purpose.
What this says is that the widget can only be applied to the facet named "myfacetname".
Hope this helps,
Chris
Comment #2
levialliance CreditAttribution: levialliance commentedHi Chris,
The reason for the custom query type is that I am querying an external (very dynamic) data source and then turning those results into solr filters -- given that the widget is so tightly coupled with the query type it didn't make any sense for the query type/widget to be used with anything other than each other. (although thanks for mentioning the 'requirements' attribute of hook_facetapi_widgets(), there is another facet that this will help immensely with).
I've looked at this a bit more now and the issue is unrelated to custom query types: trying to configure any unconfigured facet that supports exactly 1 non-term query type with a non-term widget will always fail even with a built-in query type.
I've attached a basic module that contains the bare minimum necessary code (50 lines) to demonstrate the behaviour: it only defines a custom widget and facet. If you install facetapi_slider (which only supports numeric_range) you can demonstrate the behaviour simply with the 15 lines in demo_facetapi_facet_info().
Steps to reproduce:
- Clean drupal 7.12 install with minimal profile.
- Activate Demo module (requires apachesolr, ctools, facetapi, features)
- Configure demo facet:
/admin/config/search/facetapi/apachesolr%40solr/block/demo_facet/edit
- Ensure Demo Widget is selected, click save
Preconditions
Note the 2 preconditions required for the bug to show:
[1] There are no existing settings in the {facetapi} table for that facet [else FacetapiAdapter::getFacetSettingsGlobal() returns those settings instead]
[2] hook_facetapi_facet_info() returns a facet with exactly one non-term query type [any more and facetapi_facet_display_form() will display the facet type dropdown and then the browser will pick the first option so you don't notice that the #default_value for the dropdown is invalid]
Analysis
facetapi_facet_display_form():
$global_settings = $adapter->getFacet($facet)->getSettings();
FacetapiFacet::getSettings():
FacetapiAdapter::getFacetSettingsGlobal():
The root problem is that in
FacetapiAdapter::getFacetSettingsGlobal()
, the default query type is hardcoded to 'term' irrespective of what the facet actually supports.facetapi_facet_display_form()
then hides the query type dropdown because there is only 1 option available, but #default_value is still hardcoded to 'term' so it is impossible to change because the dropown is hidden.Note that the problem of incorrect defaults applies to 'allowed operators', but there is no validation [so even though the demo facet defines itself as only supporting FACETAPI_OPERATOR_OR, if you look at the serialised facet config data in {facetapi}, it will save with 'and'].
http://drupal.org/node/1347348 may in fact be the same problem (although they didn't give enough information to know)
Fix
Attached is a patch against 7.x-2.x that sets the facet global default query type and operator to the first query type/operator present in the facet definition. (applies without changes to 7.x-1.x too)
Edit: had swapped AND and OR around in operator description
Comment #3
ohthehugemanatee CreditAttribution: ohthehugemanatee commentedBumping this, because I'm experiencing it too. A good example of a widget that doesn't support "term" is the Slider Widget referenced on FacetAPI's module page. This is a correctly defined widget (as far as I can tell!).
Then I try to create a new facet for it, for example:
(note I have both the array and singular definition in there, to be doubly sure)
This is an integer data type, numeric_range in Facet parlance. But try and select the Slider widget, and you'll get a form validation error that this widget doesn't support the "Term" query type. that error comes from facetapi.admin.inc, function facetapi_facet_display_form_validate().
It's throwing the error because the widget does not support the query type defined in $form_state['values']['global']['query_type']; , which comes from a hidden field on the form... which doesn't seem to care about the facet definition.
If it is intended to check against a hardcoded value, can someone explain why?
Otherwise, thank you levialliance for a good patch. Attaching a re-roll against the current version (rc4)
Comment #4
levialliance CreditAttribution: levialliance commented(Changed title to reflect actual problem)
Comment #5
tahiticlic CreditAttribution: tahiticlic commentedDoesn't work with latest version of Facetapi (rc4) and facetapi slider on numeric field.
Comment #6
gnucifer CreditAttribution: gnucifer commentedI have the exact same problem implementing a widget for a new query-type. This problem only appers in widgets supporting only one query type (not being term) and/or one operator (not beeing AND). Was going to start a new issue, but will submit my patch, (very similar to other patches in this tread).
Comment #7
Nick_vhAdd this in your custom module
Comment #8
gnucifer CreditAttribution: gnucifer commented@Nick_vh I'm not sure if you have misunderstood the problem. The issue occurs when defining new facets supporting one query_type (not term).
In this piece of code in facetapi.admin.inc:
if $query_types has only one element, the form element will be hidden with the default_value hard-coded to "term". So if $query_types contains the single element "my_query_type", it will not be saved, but overriden by "term", $options being ignored by FAPI when not a visible select element.
Comment #9
cpliakas CreditAttribution: cpliakas commentedI am trying to wrap my head around this. I do agree there is definitely a usability WTF here. There should at least be some JavaScript that doesn't present options that aren't valid.
An issue I see with the Facet API Slider module is that it doesn't implement requirements, so it presents itself as an option for facets that do not support the query type plugin. It is in these cases where I see the phenomenon mentioned above. For cases like number fields which do allow numeric range queries, the user is presented with an option to select the correct query type, although again JavaScript should be changing the values so it doesn't default to something that won't validate.
Thanks for all of the discussions and research around this issue. Look forward to more discussion and a better understanding of the bug.
Chris
Comment #10
cpliakas CreditAttribution: cpliakas commentedMarking as needs work, more so in helping me understand the issue fully.
Comment #11
levialliance CreditAttribution: levialliance commentedThe UI is actually doing the right thing; if there is only one query type available then it is entirely sensible to hide from the user the select box for the query type since they can only choose one value. The problem is that the forms API is being told that certain values are allowed when in fact they are not. Note that the issue is not limited to just the query_type; if you create a facet that only supports FACETAPI_OPERATOR_OR and not FACETAPI_OPERATOR_AND then you will not see an error, but the underlying facet settings in the database will be invalid.
The fundamental problem is that if a facet does not support the FACETAPI_OPERATOR_AND operator, then the default settings should not specify FACETAPI_OPERATOR_AND as the default operator as this is an illegal value. Similarly, if a facet only supports 'numeric_range' as the query type, then 'term' should not be the default query type in the facet settings as this is an illegal value.
The FacetapiAdapter::getFacetSettingsGlobal() function completely ignores the available operators and query types returned from hook_facetapi_facet_info() and insists that FACETAPI_OPERATOR_AND and 'term' will be your defaults even if these were not listed in the facet info hook. If FacetapiAdapter::getFacetSettingsGlobal() was to respect the values returned by hook_facetapi_facet_info() then there would be no UI issues.
The patch attached (recreated against 7.x-2.x git branch) simply changes the hardcoded defaults in FacetapiAdapter::getFacetSettingsGlobal() to choose the first available query type and operator.
Run the demo module at http://drupal.org/node/1443340#comment-5635674 - it demonstrates the problem in 50 lines. Note that demo_facetapi_facet_info() indicates that this facet only supports a query type of 'numeric_range' and an allowed operator of FACETAPI_OPERATOR_OR.
Activate the demo module and reset your DB settings:
now edit the facet in the admin UI, saving the facet with the default settings.
The operator is set to 'and' and the query type is 'term' even though these were not among the valid choices according to hook_facetapi_facet_info(). [For some reason the latest version of drupal + facetapi 2.x no longer throws an error, it now silently saves illegal values to the database instead]
Comment #12
cpliakas CreditAttribution: cpliakas commentedThanks for the very detailed explanation! I understand much better what the problem is and have wrapped my head around it. Marking #1443340-11: The default query type setting is hard coded to "term" which causes issues for widgets that don't support "term" queries as needs review.
Comment #13
cpliakas CreditAttribution: cpliakas commentedI totally get it now and can replicate the bug. Patch works as expected. I am refactoring a bit just to highlight exactly why to code is written as such, but marking as RTBC. Thanks for sticking with me on this one.
Chris
Comment #14
cpliakas CreditAttribution: cpliakas commentedCommitted to all active versions of Facet API.
Congrats on becoming the 28th code contributor to Facet API!
Comment #15
gnucifer CreditAttribution: gnucifer commentedIf being really anal about it, shouldn't $facet['allowed operators'] also first be filtered like:
Since a valid value for $facet['allowed operators'] could be:
and that would cause the same problem?
Either that or refactor the code so that $facet['allowed operators'] stores the allowed operators as values instead.
Comment #16
cpliakas CreditAttribution: cpliakas commentedgnucifer,
You are absolutely right, and great catch! If we take
$allowed_operators = array_filter($facet['allowed operators']);
approach that you mentioned, we can actually replace thereset($facet['allowed operators']);
statement with your snippet and read the key() of the captured variable. We don't need reset() because the internal pointer isn't transferred to the array returned by array_filter(). The attached follow-up patch takes this approach.Thanks for the contribution,
Chris
Comment #17
cpliakas CreditAttribution: cpliakas commentedThis is a small change, so I committed it to all major versions of Facet API giving gnucifer credit.
gnucifer, congrats on becoming the 29th code contributor to Facet API!
Comment #18
cpliakas CreditAttribution: cpliakas commentedAdded tests for the 7.x versions of Facet API.
Comment #20
cappadona CreditAttribution: cappadona commentedI know this has been closed for several months now, but I'm still running into this error with facetapi-7.x-1.2 and facetapi_slider-7.x-1.x-dev:
Comment #22
cpliakas CreditAttribution: cpliakas commentedRe-closing as fixed. You have to make sure that the correct query type is used, because sliders should work with term query types. They should only work with ranges. If the problem persists, I suggest opening up a new bu report with detailed steps to reproduce.
Thanks,
Chris
Comment #23
fehin CreditAttribution: fehin commentedHi cpliakas, you said
where do you set the query type? My field is ubercart Sell Price field and it was set by default to decimal in search_api field type.
Comment #24
cpliakas CreditAttribution: cpliakas commentedLet's open a separate issue for this as opposed to re-opening an old one. It helps to make sure we aren't trouble shooting multiple things in one thread.
Comment #25
fehin CreditAttribution: fehin commentedNo problem. I have opened another issue.
Comment #26
xeeshangulzar CreditAttribution: xeeshangulzar commented#3: 1443340-3facet-global-defaults-1.patch queued for re-testing.
Comment #27
francois.soulard CreditAttribution: francois.soulard commentedDear,
I still have this error while using facet api and slider widget...
Does anybody have a solution ?
Best regards,
Comment #28
Sebastien M. CreditAttribution: Sebastien M. commented3: 1443340-3facet-global-defaults-1.patch queued for re-testing.
Comment #30
surfgatinho CreditAttribution: surfgatinho commentedAny news on this? I still get this error even with the latest dev version of Facet API.
Am using 7.x-1.x-dev of facet slider and the latest dev version of Facet API.
Thanks
Comment #31
serpforge CreditAttribution: serpforge commentedMay be you can fix it already? This problem has existed for two years.
Thanks
Comment #32
f0ns CreditAttribution: f0ns commentedHi,
I also get the error:
Error message: The widget does not support the term query type
I use Facet API 1.4 with With Facet API Slider 1.0. I tried to apply widget Slider to my field price (Integer) when I get this error. Anyone has a way to quickfix this?
Comment #33
lpeabody CreditAttribution: lpeabody commentedAny update on this? @cpliakas you say this was committed (back in 2012), but I still don't see this reflected in the current codebase, 1.5. Needless to say I'm running into this error. What's the status?
EDIT: Looks like the the settings array was changed to remove the operator and query_type keys. Still, this problem appears to have resurfaced and is causing issues.