Koha/Koha/SuggestionEngine.pm
Jared Camins-Esakov d2cd2e09aa Bug 8726: ExplodedTerms suggestion plugin (functionality)
When working with hierarchical subject headings, it is sometimes helpful
to do a search for all records with a specific subject, plus
broader/narrower/related subjects. This patch adds a suggestion plugin for
these "exploded" subject searches to Koha. Note that this patch depends on
both bug 8211 AND bug 8209.

To test (NOTE: this test plan covers both 8211 and 8726):
1) Make sure you have a bunch of hierarchical subjects. I created
   geographical subjects for "Arizona," "United States," and "Phoenix,"
   and linked them together using 551s, and made sure I had a half
   dozen records linking to each (but not all to all three).
2) Do a search for su-br:Arizona (or choose "Subject and broader terms"
   on the advanced search screen with "more options" displayed), and
   check that you get the records with the subject "Arizona" and the
   records with the subject "United States"
3) Do a search for su-na:Arizona (or choose "Subject and narrower terms"
   on the advanced search screen with "more options" displayed), and
   check that you get the records with the subject "Arizona" and the
   records with the subject "Phoenix"
4) Do a search for su-rl:Arizona (or choose "Subject and related terms"
   on the advanced search screen with "more options" displayed), and
   check that you get the records with the subject "Arizona," the
   records with the subject "United States," and the records with the
   subject "Phoenix"
5) Ensure that other searches still work (keyword, subject, ccl,
   whatever)
6) Use "Did you mean?" page in admin section to enable ExplodedTerms
   plugin
7) Do a keyword search on the OPAC, confirm that searching for exploded
   terms is suggested.
8) Do a subject search on the OPAC, confirm that searching for exploded
   terms is suggested.
9) Do a non-keyword, non-subject search on the OPAC, confirm that
   searching for exploded terms is NOT suggested.
10) Disable ExplodedTerms plugin and enable AuthorityFile plugin.
11) Do search on OPAC, confirm suggestions are made from authority file.
12) Sign off

Signed-off-by: wajasu <matted-34813@mypacks.net>
Signed-off-by: Jared Camins-Esakov <jcamins@cpbibliography.com>
Split into two patches. This patch includes only the functionality.
2012-09-28 17:08:21 +02:00

199 lines
4.8 KiB
Perl

package Koha::SuggestionEngine;
# Copyright 2012 C & P Bibliography Services
#
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Koha; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
=head1 NAME
Koha::SuggestionEngine - Dispatcher class for suggestion engines
=head1 SYNOPSIS
use Koha::SuggestionEngine;
my $suggestor = Koha::SuggestionEngine->new(%params);
$suggestor->get_suggestions($search)
=head1 DESCRIPTION
Dispatcher class for retrieving suggestions. SuggestionEngines must
extend Koha::SuggestionEngine::Base, be in the Koha::SuggestionEngine::Plugin
namespace, and provide the following methods:
B<get_suggestions ($search)> - get suggestions from the plugin for the
specified search.
These methods may be overriden:
B<initialize (%params)> - initialize the plugin
B<destroy ()> - destroy the plugin
These methods should not be overridden unless you are very sure of what
you are doing:
B<new ()> - create a new plugin object
=head1 FUNCTIONS
=cut
use strict;
use warnings;
use Module::Load::Conditional qw(can_load);
use Module::Pluggable::Object;
use base qw(Class::Accessor);
__PACKAGE__->mk_accessors(qw( schema plugins options record ));
=head2 new
my $suggestor = Koha::SuggestionEngine->new(%params);
Create a new suggestor class. Available parameters are:
=over 8
=item B<plugins>
What plugin(s) to use. This must be an arrayref to a list of plugins. Plugins
can be specified either with a complete class path, or, if they are in the
Koha::SuggestionEngine::Plugin namespace, as only the plugin name, and
"Koha::SuggestionEngine::Plugin" will be prepended to it before the plugin
is loaded.
=back
=cut
sub new {
my $class = shift;
my $param = shift;
my $options = $param->{options} || '';
my @plugins = ();
foreach my $plugin ( @{$param->{plugins}} ) {
next unless $plugin;
my $plugin_module =
$plugin =~ m/:/
? $plugin
: "Koha::SuggestionEngine::Plugin::${plugin}";
if ( can_load( modules => { $plugin_module => undef } ) ) {
my $object = $plugin_module->new();
$plugin_module->initialize($param);
push @plugins, $object;
}
}
my $self = $class->SUPER::new(
{
plugins => \@plugins,
options => $options
}
);
bless $self, $class;
return $self;
}
=head2 get_suggestions
my $suggestions = $suggester->get_suggestions(\%params)
Get a list of suggestions based on the search passed in. Available parameters
are:
=over 8
=item B<search>
Required. The search for which suggestions are desired.
=item B<count>
Optional. The number of suggestions to retrieve. Defaults to 10.
=back
=cut
sub get_suggestions {
my $self = shift;
my $param = shift;
return unless $param->{'search'};
my $number = $param->{'count'} || 10;
my %suggestions;
my $index = scalar @{ $self->plugins };
foreach my $pluginobj ( @{ $self->plugins } ) {
next unless $pluginobj;
my $pluginres = $pluginobj->get_suggestions($param);
foreach my $suggestion (@$pluginres) {
$suggestions{ $suggestion->{'search'} }->{'relevance'} +=
$suggestion->{'relevance'} * $index;
$suggestions{ $suggestion->{'search'} }->{'label'} |=
$suggestion->{'label'};
}
$index--;
}
my @results = ();
for (
sort {
$suggestions{$b}->{'relevance'} <=> $suggestions{$a}->{'relevance'}
} keys %suggestions
)
{
last if ( $#results == $number - 1 );
push @results,
{
'search' => $_,
relevance => $suggestions{$_}->{'relevance'},
label => $suggestions{$_}->{'label'}
};
}
return \@results;
}
sub DESTROY {
my $self = shift;
foreach my $pluginobj ( @{ $self->plugins } ) {
$pluginobj->destroy();
}
}
=head2 AvailablePlugins
my @available_plugins = Koha::SuggestionEngine::AvailablePlugins();
Get a list of available plugins.
=cut
sub AvailablePlugins {
my $path = 'Koha::SuggestionEngine::Plugin';
my $finder = Module::Pluggable::Object->new( search_path => $path );
return $finder->plugins;
}
1;