-
Notifications
You must be signed in to change notification settings - Fork 359
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
Support filters and custom heading on recommendation modules #3192
Conversation
@@ -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')) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
config/vufind/searches.ini
Outdated
@@ -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] |
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a TODO
There was a problem hiding this comment.
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.
There was a problem hiding this 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
@@ -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] |
There was a problem hiding this comment.
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.
@@ -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')) { |
There was a problem hiding this comment.
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.
There was a problem hiding this 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
; 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. |
There was a problem hiding this comment.
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.
- [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.
- 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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this 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; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call
There was a problem hiding this 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?
All set. |
There was a problem hiding this 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!
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:
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.
TODO
:[hidden filters key]:[custom heading]
to the rest of the affected modules in searches.ini