Bug 16436 [QA Followup] - Use debug instead of info
[koha.git] / C4 / Log.pm
1 package C4::Log;
2
3 #package to deal with Logging Actions in DB
4
5
6 # Copyright 2000-2002 Katipo Communications
7 # Copyright 2011 MJ Ray and software.coop
8 #
9 # This file is part of Koha.
10 #
11 # Koha is free software; you can redistribute it and/or modify it
12 # under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 3 of the License, or
14 # (at your option) any later version.
15 #
16 # Koha is distributed in the hope that it will be useful, but
17 # WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
20 #
21 # You should have received a copy of the GNU General Public License
22 # along with Koha; if not, see <http://www.gnu.org/licenses>.
23
24 use strict;
25 use warnings;
26
27 use JSON qw( to_json );
28
29 use C4::Context;
30 use Koha::DateUtils;
31 use Koha::Logger;
32
33 use vars qw(@ISA @EXPORT);
34
35 BEGIN {
36         require Exporter;
37         @ISA = qw(Exporter);
38         @EXPORT = qw(&logaction &cronlogaction &GetLogStatus &displaylog &GetLogs);
39 }
40
41 =head1 NAME
42
43 C4::Log - Koha Log Facility functions
44
45 =head1 SYNOPSIS
46
47   use C4::Log;
48
49 =head1 DESCRIPTION
50
51 The functions in this module perform various functions in order to log all the operations done on the Database, including deleting and undeleting books, adding/editing members, etc.
52
53 =head1 FUNCTIONS
54
55 =over 2
56
57 =item logaction
58
59   &logaction($modulename, $actionname, $objectnumber, $infos);
60
61 Adds a record into action_logs table to report the different changes upon the database.
62 Each log entry includes the number of the user currently logged in.  For batch
63 jobs, which operate without authenticating a user and setting up a session, the user
64 number is set to 0, which is the same as the superlibrarian's number.
65
66 =cut
67
68 #'
69 sub logaction {
70     my ($modulename, $actionname, $objectnumber, $infos)=@_;
71
72     # Get ID of logged in user.  if called from a batch job,
73     # no user session exists and C4::Context->userenv() returns
74     # the scalar '0'.
75     my $userenv = C4::Context->userenv();
76     my $usernumber = (ref($userenv) eq 'HASH') ? $userenv->{'number'} : 0;
77     $usernumber ||= 0;
78
79     my $dbh = C4::Context->dbh;
80     my $sth=$dbh->prepare("Insert into action_logs (timestamp,user,module,action,object,info) values (now(),?,?,?,?,?)");
81     $sth->execute($usernumber,$modulename,$actionname,$objectnumber,$infos);
82     $sth->finish;
83
84     my $logger = Koha::Logger->get(
85         {
86             interface => 'intranet',
87             category  => "ActionLogs.$modulename.$actionname"
88         }
89     );
90     $logger->debug(
91         sub {
92             "ACTION LOG: " . to_json(
93                 {
94                     user   => $usernumber,
95                     module => $modulename,
96                     action => $actionname,
97                     object => $objectnumber,
98                     info   => $infos
99                 }
100             );
101         }
102     );
103 }
104
105 =item cronlogaction
106
107   &cronlogaction($infos);
108
109 Convenience routine to add a record into action_logs table from a cron job.
110 Logs the path and name of the calling script plus the information privided by param $infos.
111
112 =cut
113
114 #'
115 sub cronlogaction {
116     my ($infos)=@_;
117     my $loginfo = (caller(0))[1];
118     $loginfo .= ' ' . $infos if $infos;
119     logaction( 'CRONJOBS', 'Run', undef, $loginfo ) if C4::Context->preference('CronjobLog');
120 }
121
122
123 =item GetLogStatus
124
125   $status = GetLogStatus;
126
127 C<$status> is a hasref like this example:
128     $hash = {
129         BorrowersLog   => 1,
130         CataloguingLog => 0,
131         IssueLog       => 0,
132         ...
133     }
134
135 =cut
136
137 #'
138 sub GetLogStatus {
139     my %hash;
140     $hash{BorrowersLog}    = C4::Context->preference("BorrowersLog");
141     $hash{CataloguingLog}  = C4::Context->preference("CataloguingLog");
142     $hash{IssueLog}        = C4::Context->preference("IssueLog");
143     $hash{ReturnLog}       = C4::Context->preference("ReturnLog");
144     $hash{SubscriptionLog} = C4::Context->preference("SubscriptionLog");
145     $hash{LetterLog}       = C4::Context->preference("LetterLog");
146     $hash{FinesLog}        = C4::Context->preference("FinesLog");
147     return \%hash;
148 }
149
150 =item displaylog
151
152   &displaylog($modulename, @filters);
153   $modulename is the name of the module on which the user wants to display logs
154   @filters is an optional table of hash containing :
155       - name : the name of the variable to filter
156     - value : the value of the filter.... May be with * joker
157
158 returns a table of hash containing who did what on which object at what time
159
160 =cut
161
162 #'
163 sub displaylog {
164   my ($modulename, @filters) = @_;
165     my $dbh = C4::Context->dbh;
166     my $strsth=qq|
167                 SELECT action_logs.timestamp, action_logs.action, action_logs.info,
168                                 borrowers.cardnumber, borrowers.surname, borrowers.firstname, borrowers.userid,
169                         biblio.biblionumber, biblio.title, biblio.author
170         FROM action_logs
171                 LEFT JOIN borrowers ON borrowers.borrowernumber=action_logs.user
172         LEFT JOIN  biblio   ON action_logs.object=biblio.biblionumber
173         WHERE action_logs.module = 'cataloguing'
174         |;
175         my %filtermap = ();
176     if ($modulename eq "catalogue" or $modulename eq "acqui") {
177                 %filtermap = (
178                           user => 'borrowers.surname',
179                          title => 'biblio.title',
180                         author => 'biblio.author',
181                 );
182     } elsif ($modulename eq "members") {
183         $strsth=qq|
184                 SELECT action_logs.timestamp, action_logs.action, action_logs.info,
185                         borrowers.cardnumber, borrowers.surname, borrowers.firstname, borrowers.userid,
186                         bor2.cardnumber, bor2.surname, bor2.firstname, bor2.userid
187         FROM action_logs
188                 LEFT JOIN borrowers ON borrowers.borrowernumber=action_logs.user
189                 LEFT JOIN borrowers as bor2 ON action_logs.object=bor2.borrowernumber
190         WHERE action_logs.module = 'members'
191                 |;
192                 %filtermap = (
193                        user => 'borrowers.surname',
194                     surname => 'bor2.surname',
195                   firstname => 'bor2.firstname',
196                  cardnumber => 'bor2.cardnumber',
197                 );
198     } else {
199                 return 0;
200         }
201
202     if (@filters) {
203                 foreach my $filter (@filters) {
204                         my $tempname = $filter->{name}         or next;
205                         (grep {/^$tempname$/} keys %filtermap) or next;
206                         $filter->{value} =~ s/\*/%/g;
207                         $strsth .= " AND " . $filtermap{$tempname} . " LIKE " . $filter->{value};
208                 }
209         }
210     my $sth=$dbh->prepare($strsth);
211     $sth->execute;
212     my @results;
213     my $count;
214     my $hilighted=1;
215     while (my $data = $sth->fetchrow_hashref){
216         $data->{hilighted} = ($hilighted>0);
217         $data->{info} =~ s/\n/<br\/>/g;
218         $data->{day} = output_pref({ str => $data->{timestamp} });
219         push @results, $data;
220         $count++;
221         $hilighted = -$hilighted;
222     }
223     return ($count, \@results);
224 }
225
226 =item GetLogs
227
228 $logs = GetLogs($datefrom,$dateto,$user,\@modules,$action,$object,$info);
229
230 Return:
231 C<$logs> is a ref to a hash which containts all columns from action_logs
232
233 =cut
234
235 sub GetLogs {
236     my $datefrom = shift;
237     my $dateto   = shift;
238     my $user     = shift;
239     my $modules  = shift;
240     my $action   = shift;
241     my $object   = shift;
242     my $info     = shift;
243
244     my $iso_datefrom = $datefrom ? output_pref({ dt => dt_from_string( $datefrom ), dateformat => 'iso', dateonly => 1 }) : undef;
245     my $iso_dateto = $dateto ? output_pref({ dt => dt_from_string( $dateto ), dateformat => 'iso', dateonly => 1 }) : undef;
246
247     $user ||= q{};
248
249     my $dbh   = C4::Context->dbh;
250     my $query = "
251         SELECT *
252         FROM   action_logs
253         WHERE 1
254     ";
255
256     my @parameters;
257     $query .=
258       " AND DATE_FORMAT(timestamp, '%Y-%m-%d') >= \"" . $iso_datefrom . "\" "
259       if $iso_datefrom;    #fix me - mysql specific
260     $query .=
261       " AND DATE_FORMAT(timestamp, '%Y-%m-%d') <= \"" . $iso_dateto . "\" "
262       if $iso_dateto;
263     if ( $user ne q{} ) {
264         $query .= " AND user = ? ";
265         push( @parameters, $user );
266     }
267     if ( $modules && scalar(@$modules) ) {
268         $query .=
269           " AND module IN (" . join( ",", map { "?" } @$modules ) . ") ";
270         push( @parameters, @$modules );
271     }
272     if ( $action && scalar(@$action) ) {
273         $query .= " AND action IN (" . join( ",", map { "?" } @$action ) . ") ";
274         push( @parameters, @$action );
275     }
276     if ($object) {
277         $query .= " AND object = ? ";
278         push( @parameters, $object );
279     }
280     if ($info) {
281         $query .= " AND info LIKE ? ";
282         push( @parameters, "%" . $info . "%" );
283     }
284
285     my $sth = $dbh->prepare($query);
286     $sth->execute(@parameters);
287
288     my @logs;
289     while ( my $row = $sth->fetchrow_hashref ) {
290         push @logs, $row;
291     }
292     return \@logs;
293 }
294
295 1;
296 __END__
297
298 =back
299
300 =head1 AUTHOR
301
302 Koha Development Team <http://koha-community.org/>
303
304 =cut