Bug 4173: Followup: Document KohaAuthorisedValues plugin
[koha.git] / Koha / SuggestionEngine.pm
1 package Koha::SuggestionEngine;
2
3 # Copyright 2012 C & P Bibliography Services
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
10 # version.
11 #
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License along
17 # with Koha; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20 =head1 NAME
21
22 Koha::SuggestionEngine - Dispatcher class for suggestion engines
23
24 =head1 SYNOPSIS
25
26   use Koha::SuggestionEngine;
27   my $suggestor = Koha::SuggestionEngine->new(%params);
28   $suggestor->get_suggestions($search)
29
30 =head1 DESCRIPTION
31
32 Dispatcher class for retrieving suggestions. SuggestionEngines must
33 extend Koha::SuggestionEngine::Base, be in the Koha::SuggestionEngine::Plugin
34 namespace, and provide the following methods:
35
36 B<get_suggestions ($search)> - get suggestions from the plugin for the
37 specified search.
38
39 These methods may be overriden:
40
41 B<initialize (%params)> - initialize the plugin
42
43 B<destroy ()> - destroy the plugin
44
45 These methods should not be overridden unless you are very sure of what
46 you are doing:
47
48 B<new ()> - create a new plugin object
49
50 =head1 FUNCTIONS
51
52 =cut
53
54 use strict;
55 use warnings;
56 use Module::Load::Conditional qw(can_load);
57 use Module::Pluggable::Object;
58
59 use base qw(Class::Accessor);
60
61 __PACKAGE__->mk_accessors(qw( schema plugins options record ));
62
63 =head2 new
64
65     my $suggestor = Koha::SuggestionEngine->new(%params);
66
67 Create a new suggestor class. Available parameters are:
68
69 =over 8
70
71 =item B<plugins>
72
73 What plugin(s) to use. This must be an arrayref to a list of plugins. Plugins
74 can be specified either with a complete class path, or, if they are in the
75 Koha::SuggestionEngine::Plugin namespace, as only the plugin name, and
76 "Koha::SuggestionEngine::Plugin" will be prepended to it before the plugin
77 is loaded.
78
79 =back
80
81 =cut
82
83 sub new {
84     my $class = shift;
85     my $param = shift;
86
87     my $options = $param->{options} || '';
88     my @plugins = ();
89
90     foreach my $plugin ( $param->{plugins} ) {
91         next unless $plugin;
92         my $plugin_module =
93             $plugin =~ m/:/
94           ? $plugin
95           : "Koha::SuggestionEngine::Plugin::${plugin}";
96         if ( can_load( modules => { $plugin_module => undef } ) ) {
97             my $object = $plugin_module->new();
98             $plugin_module->initialize($param);
99             push @plugins, $object;
100         }
101     }
102
103     my $self = $class->SUPER::new(
104         {
105             plugins => \@plugins,
106             options => $options
107         }
108     );
109     bless $self, $class;
110     return $self;
111 }
112
113 =head2 get_suggestions
114
115     my $suggestions = $suggester->get_suggestions(\%params)
116
117 Get a list of suggestions based on the search passed in. Available parameters
118 are:
119
120 =over 8
121
122 =item B<search>
123
124 Required. The search for which suggestions are desired.
125
126 =item B<count>
127
128 Optional. The number of suggestions to retrieve. Defaults to 10.
129
130 =back
131
132 =cut
133
134 sub get_suggestions {
135     my $self  = shift;
136     my $param = shift;
137
138     return unless $param->{'search'};
139
140     my $number = $param->{'count'} || 10;
141
142     my %suggestions;
143
144     foreach my $pluginobj ( @{ $self->plugins } ) {
145         next unless $pluginobj;
146         my $pluginres = $pluginobj->get_suggestions($param);
147         foreach my $suggestion (@$pluginres) {
148             $suggestions{ $suggestion->{'search'} }->{'relevance'} +=
149               $suggestion->{'relevance'};
150             $suggestions{ $suggestion->{'search'} }->{'label'} |=
151               $suggestion->{'label'};
152         }
153     }
154
155     my @results = ();
156     for (
157         sort {
158             $suggestions{$b}->{'relevance'} <=> $suggestions{$a}->{'relevance'}
159         } keys %suggestions
160       )
161     {
162         last if ( $#results == $number - 1 );
163         push @results,
164           {
165             'search'  => $_,
166             relevance => $suggestions{$_}->{'relevance'},
167             label     => $suggestions{$_}->{'label'}
168           };
169     }
170
171     return \@results;
172 }
173
174 sub DESTROY {
175     my $self = shift;
176
177     foreach my $pluginobj ( @{ $self->plugins } ) {
178         $pluginobj->destroy();
179     }
180 }
181
182 =head2 AvailablePlugins
183
184     my @available_plugins = Koha::SuggestionEngine::AvailablePlugins();
185
186 Get a list of available plugins.
187
188 =cut
189
190 sub AvailablePlugins {
191     my $path = 'Koha::SuggestionEngine::Plugin';
192     my $finder = Module::Pluggable::Object->new( search_path => $path );
193     return $finder->plugins;
194 }
195
196 1;