Problem/Motivation
The "Show only deepest item levels" processor (ShowOnlyDeepestLevelItemsProcessor) is supposed to hide any facet result that has children, leaving only leaf-level items visible. It is not working with facets_exposed_filters, for two independent reasons:
supportsFacet()is gated tofacet_entityonly. The processor'ssupportsFacet()hardcodes support to$facet->getFacetType() == 'facet_entity', with a@todo Support "facets_exposed_filter".comment acknowledging the gap. Any facet exposed as a Views filter via the Facets Exposed Filters submodule hasfacet_type == 'facets_exposed_filter'at runtime, so the processor is excluded from that facet's pipeline entirely — it never even appears as a configurable option on the Views filter's settings form.- Processor ordering. Once the type restriction above is lifted, the processor still has no effect: it declares a default
buildstage weight of40, whileHierarchyProcessor— the processor that actually populates each result's children viasetChildren()— declares a weight of100. Processors run in ascending weight order, soShowOnlyDeepestLevelItemsProcessor::build()runs before the hierarchy tree is built. Its checkif (!empty($result->getChildren())) { unset($results[$id]); }always sees an empty children array, so no result is ever excluded.
Reweighting the processor to run after HierarchyProcessor is not sufficient by itself, and surfaces a third, previously-latent bug:
build()'s removal logic discards children along with their parent.HierarchyProcessor::build()deliberately removes child results from the top-level results array once they are nested under their parent (its own code comment: "Remove children from primary level").ShowOnlyDeepestLevelItemsProcessor::build()only ever removes a parent when it has children — it has no logic to promote that parent's children back into the flat results array in its place. Once the ordering bug (2) is fixed and the processor actually runs against a built hierarchy tree, it removes every parent correctly, but their children vanish along with them instead of surfacing as the intended "deepest level" items. Only fixing (1) and (2) together produces a facet that shows no results below the top level at all, worse than doing nothing.
Steps to reproduce
- Create a hierarchical taxonomy vocabulary with at least one parent term that has children.
- Create a Search API facet on that field, with "Use hierarchy" enabled and hierarchy type "Taxonomy."
- Expose the field as a Views filter via the Facets Exposed Filters submodule (
facets_filterplugin). Observe: the "Show only deepest item levels" processor is not offered as a selectable processor on the filter's settings form at all (bug 1). - Patch
supportsFacet()only and add the processor to the filter'sprocessor_configsat its default weight. Observe: parent and child terms all still display (bug 2, ordering). - Additionally reweight the processor to run after
hierarchy_processor, without changingbuild(). Observe: both parent and child terms disappear — only childless top-level terms remain (bug 3, children are not promoted after their parent is removed).
Proposed resolution
- Update
ShowOnlyDeepestLevelItemsProcessor::supportsFacet()to also allowfacet_type == 'facets_exposed_filter', removing the@todo. - Change the processor's declared
buildstage weight from40to a value greater thanHierarchyProcessor's100(e.g.110), so it runs after the hierarchy tree is built andgetChildren()is populated. - Rewrite
build()to recursively descend into each result's children and collect only the leaves (results with no children of their own), rather than simply unsetting any result that has children. This requires no additional queries: it operates purely on the hierarchy treeHierarchyProcessoralready built via a single batchedgetChildIds()call, which matters for taxonomies with large numbers of terms since that call is not batched into a single query internally.
Remaining tasks
- Patch and manual testing against both a classic Facets block and a Facets Exposed Filters (Views) placement, across more than one level of hierarchy depth.
- Confirm no other core/contrib processor depends on
ShowOnlyDeepestLevelItemsProcessorrunning at its current weight of40relative to processors between weight 40 and 100 (e.g.CountLimitProcessor,ExcludeSpecifiedItemsProcessor,HideOnlyOneItemProcessor, all at weight 50) before finalizing the new weight value.
User interface changes
None. The processor becomes selectable in the Views exposed-filter processor settings form for facets of type facets_exposed_filter, where it was previously silently omitted.
API changes
None. The processor's plugin ID and configuration schema are unchanged. The plugin annotation's declared default weight, the supportsFacet() return condition, and the internal implementation of build() change; a new protected helper method is added. No public method signatures change.
Data model changes
None.
| Comment | File | Size | Author |
|---|---|---|---|
| #6 | facets-3616544-3.0.3.patch | 1.95 KB | ckng |
Issue fork facets-3616544
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
ckngComment #5
ckngComment #6
ckngPatch file against 3.0.3, in case anyone need it.
MR is against 3.0.x-dev.