Bug 8585 : Add System Preference to specify Holds to Pull List Start Date
[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     my $index = scalar @{ $self->plugins };
145
146     foreach my $pluginobj ( @{ $self->plugins } ) {
147         next unless $pluginobj;
148         my $pluginres = $pluginobj->get_suggestions($param);
149         foreach my $suggestion (@$pluginres) {
150             $suggestions{ $suggestion->{'search'} }->{'relevance'} +=
151               $suggestion->{'relevance'} * $index;
152             $suggestions{ $suggestion->{'search'} }->{'label'} |=
153               $suggestion->{'label'};
154         }
155         $index--;
156     }
157
158     my @results = ();
159     for (
160         sort {
161             $suggestions{$b}->{'relevance'} <=> $suggestions{$a}->{'relevance'}
162         } keys %suggestions
163       )
164     {
165         last if ( $#results == $number - 1 );
166         push @results,
167           {
168             'search'  => $_,
169             relevance => $suggestions{$_}->{'relevance'},
170             label     => $suggestions{$_}->{'label'}
171           };
172     }
173
174     return \@results;
175 }
176
177 sub DESTROY {
178     my $self = shift;
179
180     foreach my $pluginobj ( @{ $self->plugins } ) {
181         $pluginobj->destroy();
182     }
183 }
184
185 =head2 AvailablePlugins
186
187     my @available_plugins = Koha::SuggestionEngine::AvailablePlugins();
188
189 Get a list of available plugins.
190
191 =cut
192
193 sub AvailablePlugins {
194     my $path = 'Koha::SuggestionEngine::Plugin';
195     my $finder = Module::Pluggable::Object->new( search_path => $path );
196     return $finder->plugins;
197 }
198
199 1;