Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support filters and custom heading on recommendation modules #3192

Merged
merged 17 commits into from
Nov 14, 2023

Conversation

maccabeelevine
Copy link
Member

@maccabeelevine maccabeelevine commented Nov 3, 2023

This adds a hiddenFilter capability on recommendation modules that derive from AbstractSearchObject. It also adds an optional custom heading.

I have a few specific use cases in mind:

  • The primary search results are from a tab with a hidden filter -- say a media-specific Solr search. An EDSResults sidebar could show media-specific results from EDS (or pick your other backend).
  • The primary search results are blended, but filters narrow down the results from one or more backend. A recommendation module could search the same backend but apply a different filter.
  • The primary search results are combined, and include several Solr bentos, each filtered on "high use" content like books or media. As above, a CatalogResults recommendation module called something like "Additional Sources" could be filtered on the combined NOT of all of the bentos, i.e. all the other resources no one will actually use, that we don't want in the more prominent bento real estate.

As a visual for demonstration only, here's an EDS primary results that also has a CatalogResults recommendation module that I've randomly filtered on videos.

image

TODO

  • Add :[hidden filters key]:[custom heading] to the rest of the affected modules in searches.ini
  • Add deprecation notes to changelog and JIRA about InjectSearchRunnerFactory when merging

@@ -70,6 +70,10 @@ public function __invoke(
if (!empty($options)) {
throw new \Exception('Unexpected options passed to factory.');
}
return new $requestedName($container->get(SearchRunner::class));
$module = new $requestedName($container->get(SearchRunner::class));
if (method_exists($module, 'setConfigManager')) {
Copy link
Member Author

@maccabeelevine maccabeelevine Nov 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First off, there may be a better way to make the config manager available within the recommendation module. Even if not, method_exists seems ugly but I'm not sure what is best. Maybe an interface that I check with instanceof, and define the setter in a trait? But that seems overkill and I couldn't come up with a middle ground.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the solution is just to create a different factory. The InjectSearchRunnerFactory is designed to do exactly what it says: inject the SearchRunner into the constructor. But now you want to inject the SearchRunner AND set the config manager. Maybe the easiest solution is to create an AbstractSearchObjectFactory -- then you can do all the injections you want safely since the factory is tailored for AbstractSearchObject and can assume that's how it will be used.

(I think the only reason we have InjectSearchRunnerFactory is because the various Results modules didn't inherit from a common base until you refactored them, and we probably didn't think to change the factory at that time).

In any case, if you agree with this approach, we can change all the Results modules and see if anything else is still using InjectSearchRunnerFactory. If not, we can probably deprecate it and remove it in 11.0.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense; implemented. And yes InjectSearchRunnerFactory is only used for those specific modules.

@@ -254,10 +254,14 @@ WorkKeys = year
;
; Available modules recommended for use in the side area:
;
; CatalogResults:[GET parameter]:[result limit]
; CatalogResults:[GET parameter]:[result limit]:[hidden filters key]:[custom heading]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[hidden filters key] would work in any AbstractSearchObject recommendation module. [custom heading] would also if I update the templates. I don't know how far to go documenting that for each of these recommendation modules. Every AbstractSearchObject recommendation module already has a lot of duplicate explanation (which makes sense since they're near-identical implementations).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worth applying similar language to all the other modules in this family, though I don't mind waiting until everything is finalized first since the details might change in the meantime. If you prefer to wait, we should put a TODO checkbox at the top of the PR to keep track of this item.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a TODO

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might also refactor the various AbstractSearchObject modules somehow so this explanation can be in a single place under side modules.

@maccabeelevine maccabeelevine marked this pull request as ready for review November 3, 2023 21:34
@demiankatz demiankatz added this to the 10.0 milestone Nov 6, 2023
Copy link
Member

@demiankatz demiankatz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @maccabeelevine -- I haven't done a thorough review or test yet, but I started by replying to your comments and sharing a few general ideas. :-)

config/vufind/searches.ini Outdated Show resolved Hide resolved
@@ -254,10 +254,14 @@ WorkKeys = year
;
; Available modules recommended for use in the side area:
;
; CatalogResults:[GET parameter]:[result limit]
; CatalogResults:[GET parameter]:[result limit]:[hidden filters key]:[custom heading]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worth applying similar language to all the other modules in this family, though I don't mind waiting until everything is finalized first since the details might change in the meantime. If you prefer to wait, we should put a TODO checkbox at the top of the PR to keep track of this item.

config/vufind/searches.ini Outdated Show resolved Hide resolved
themes/bootstrap3/templates/Recommend/CatalogResults.phtml Outdated Show resolved Hide resolved
@@ -70,6 +70,10 @@ public function __invoke(
if (!empty($options)) {
throw new \Exception('Unexpected options passed to factory.');
}
return new $requestedName($container->get(SearchRunner::class));
$module = new $requestedName($container->get(SearchRunner::class));
if (method_exists($module, 'setConfigManager')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the solution is just to create a different factory. The InjectSearchRunnerFactory is designed to do exactly what it says: inject the SearchRunner into the constructor. But now you want to inject the SearchRunner AND set the config manager. Maybe the easiest solution is to create an AbstractSearchObjectFactory -- then you can do all the injections you want safely since the factory is tailored for AbstractSearchObject and can assume that's how it will be used.

(I think the only reason we have InjectSearchRunnerFactory is because the various Results modules didn't inherit from a common base until you refactored them, and we probably didn't think to change the factory at that time).

In any case, if you agree with this approach, we can change all the Results modules and see if anything else is still using InjectSearchRunnerFactory. If not, we can probably deprecate it and remove it in 11.0.

@maccabeelevine maccabeelevine changed the title Support hidden filters on recommendation modules Support hidden filters and custom heading on recommendation modules Nov 6, 2023
Copy link
Member

@demiankatz demiankatz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @maccabeelevine, this is shaping up nicely. A couple more minor suggestions below. Once you've responded to those, I think it should be safe to finish up the remaining documentation formatting.

I've added a TODO note to myself to document the deprecation of the old factory.

I'll do some hands-on testing of this once you've responded to this latest round of feedback.

config/vufind/searches.ini Outdated Show resolved Hide resolved
Comment on lines 313 to 328
; LibGuidesResults:[GET parameter]:[result limit]:[ini section]:[custom heading]
; Display LibGuides research guides search results matching the terms found in
; the specified GET parameter (default = "lookfor"), limited to a specified
; number of matches (default = 5).
; Hidden filters may be defined in the specified section of the LibGuides.ini
; file; see [CatalogResultsVideoFilter] below for an example of this. The
; optional custom heading overrides the default for this recommendation module.
; LibGuidesResultsDeferred:[GET parameter]:[result limit]
; Same as LibGuidesResults, but loaded via AJAX.
; LibGuidesAZResults:[GET parameter]:[result limit]
; LibGuidesAZResults:[GET parameter]:[result limit]:[ini section]:[custom heading]
; Display LibGuides A-Z Databases search results matching the terms found in
; the specified GET parameter (default = "lookfor"), limited to a specified
; number of matches (default = 5).
; Hidden filters may be defined in the specified section of the LibGuidesAZ.ini
; file; see [CatalogResultsVideoFilter] below for an example of this. The
; optional custom heading overrides the default for this recommendation module.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added the documentation to these other modules for discussion purposes. Two obvious problems though.

  1. [custom heading] doesn't work until I implement it in the templates. I can either add it to the templates or remove it from the doc for now.
  2. Filtering doesn't work for many of these backends -- definitely not for LibGuides / LibGuidesAZ, not yet implemented for EPF, and I don't know about Web. I assume it's implemented for Summon but can't test that. So I'll presumably remove the [ini section] from those but wanted to get your take first.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1.) I think you might as well go ahead and implement the custom headings for all of the templates. I wonder if it would actually make sense to just create a $heading property and getHeading() method in AbstractSearchObject. Each AbstractSearchObject subclass could set a different default property, and then the template could just display the result of calling getHeading(). Then it's a single configurable setting instead of an override option.

2.) Maybe you should reverse the order of the heading and ini section settings so it makes more sense to drop the ini section when unsupported. Otherwise you'll have to put in an extra colon separator to override the heading, and that might cause confusion. I also wonder if we should drop the word "hidden" since we're not using hidden filters here, just regular filters. We're filtering the results fetched from the backends, but we don't need to use the hidden filter mechanism since this isn't a normal user-initiated search with faceting/filtering controls. And regarding where filtering is supported, you're correct that it should work for Summon. It should also work for Web, since that's a standard Solr-based search.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all made sense to me. I've implemented the default heading property as an abstract method so it's easier to check compliance. Everything else I did as suggested.

I forgot that we removed the client-side filtering settings from EDS.ini recently since they don't work. So I removed the [ini section] for EDS and EPF, although it's something that's worth investigating along with the larger issue.

I will need help from someone to test the Summon and Web functionality.

@demiankatz demiankatz added the small Minor changes to relatively few files label Nov 7, 2023
@maccabeelevine maccabeelevine changed the title Support hidden filters and custom heading on recommendation modules Support filters and custom heading on recommendation modules Nov 7, 2023
Copy link
Member

@demiankatz demiankatz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One minor suggestion. Once this is adjusted, I'll help test WebResults. I think we'll have to take Summon on faith (but given the nature of the changes, I'm okay with that).

*
* @var string
*/
protected $iniSection;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe call this $filterIniSection in case we have another .ini section for some other thing in future?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call

Copy link
Member

@demiankatz demiankatz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The recent merge of #3209 has created a bunch of conflicts here. Do you mind resolving them when time permits?

@maccabeelevine
Copy link
Member Author

The recent merge of #3209 has created a bunch of conflicts here. Do you mind resolving them when time permits?

All set.

Copy link
Member

@demiankatz demiankatz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me, and I tested that WebResults works as expected. Thanks again!

@demiankatz demiankatz merged commit ec7a698 into vufind-org:dev Nov 14, 2023
7 checks passed
@maccabeelevine maccabeelevine deleted the recommendation-filter branch November 14, 2023 22:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
improvement small Minor changes to relatively few files
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants