Bug 13889: Add information about cron jobs to system log
[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 C4::Context;
28 use C4::Dates qw(format_date);
29
30 use vars qw($VERSION @ISA @EXPORT);
31
32 BEGIN {
33     # set the version for version checking
34     $VERSION = 3.07.00.049;
35         require Exporter;
36         @ISA = qw(Exporter);
37         @EXPORT = qw(&logaction &cronlogaction &GetLogStatus &displaylog &GetLogs);
38 }
39
40 =head1 NAME
41
42 C4::Log - Koha Log Facility functions
43
44 =head1 SYNOPSIS
45
46   use C4::Log;
47
48 =head1 DESCRIPTION
49
50 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.
51
52 =head1 FUNCTIONS
53
54 =over 2
55
56 =item logaction
57
58   &logaction($modulename, $actionname, $objectnumber, $infos);
59
60 Adds a record into action_logs table to report the different changes upon the database.
61 Each log entry includes the number of the user currently logged in.  For batch
62 jobs, which operate without authenticating a user and setting up a session, the user
63 number is set to 0, which is the same as the superlibrarian's number.
64
65 =cut
66
67 #'
68 sub logaction {
69     my ($modulename, $actionname, $objectnumber, $infos)=@_;
70
71     # Get ID of logged in user.  if called from a batch job,
72     # no user session exists and C4::Context->userenv() returns
73     # the scalar '0'.
74     my $userenv = C4::Context->userenv();
75     my $usernumber = (ref($userenv) eq 'HASH') ? $userenv->{'number'} : 0;
76     $usernumber ||= 0;
77
78     my $dbh = C4::Context->dbh;
79     my $sth=$dbh->prepare("Insert into action_logs (timestamp,user,module,action,object,info) values (now(),?,?,?,?,?)");
80     $sth->execute($usernumber,$modulename,$actionname,$objectnumber,$infos);
81     $sth->finish;
82 }
83
84 =item cronlogaction
85
86   &cronlogaction();
87
88 Convenience routine to add a record into action_logs table from a cron job.
89
90 =cut
91
92 #'
93 sub cronlogaction {
94     logaction( 'CRONJOBS', 'Run', 0, (caller(0))[1] ) if C4::Context->preference('CronjobLog');
95 }
96
97
98 =item GetLogStatus
99
100   $status = GetLogStatus;
101
102 C<$status> is a hasref like this example:
103     $hash = {
104         BorrowersLog   => 1,
105         CataloguingLog => 0,
106         IssueLog       => 0,
107         ...
108     }
109
110 =cut
111
112 #'
113 sub GetLogStatus {
114     my %hash;
115     $hash{BorrowersLog}    = C4::Context->preference("BorrowersLog");
116     $hash{CataloguingLog}  = C4::Context->preference("CataloguingLog");
117     $hash{IssueLog}        = C4::Context->preference("IssueLog");
118     $hash{ReturnLog}       = C4::Context->preference("ReturnLog");
119     $hash{SubscriptionLog} = C4::Context->preference("SubscriptionLog");
120     $hash{LetterLog}       = C4::Context->preference("LetterLog");
121     $hash{FinesLog}        = C4::Context->preference("FinesLog");
122     return \%hash;
123 }
124
125 =item displaylog
126
127   &displaylog($modulename, @filters);
128   $modulename is the name of the module on which the user wants to display logs
129   @filters is an optional table of hash containing :
130       - name : the name of the variable to filter
131     - value : the value of the filter.... May be with * joker
132
133 returns a table of hash containing who did what on which object at what time
134
135 =cut
136
137 #'
138 sub displaylog {
139   my ($modulename, @filters) = @_;
140     my $dbh = C4::Context->dbh;
141     my $strsth=qq|
142                 SELECT action_logs.timestamp, action_logs.action, action_logs.info,
143                                 borrowers.cardnumber, borrowers.surname, borrowers.firstname, borrowers.userid,
144                         biblio.biblionumber, biblio.title, biblio.author
145         FROM action_logs 
146                 LEFT JOIN borrowers ON borrowers.borrowernumber=action_logs.user 
147         LEFT JOIN  biblio   ON action_logs.object=biblio.biblionumber
148         WHERE action_logs.module = 'cataloguing' 
149         |;
150         my %filtermap = ();
151     if ($modulename eq "catalogue" or $modulename eq "acqui") {
152                 %filtermap = (
153                           user => 'borrowers.surname',
154                          title => 'biblio.title',
155                         author => 'biblio.author',
156                 );
157     } elsif ($modulename eq "members") {
158         $strsth=qq|
159                 SELECT action_logs.timestamp, action_logs.action, action_logs.info, 
160                         borrowers.cardnumber, borrowers.surname, borrowers.firstname, borrowers.userid,
161                         bor2.cardnumber, bor2.surname, bor2.firstname, bor2.userid
162         FROM action_logs 
163                 LEFT JOIN borrowers ON borrowers.borrowernumber=action_logs.user 
164                 LEFT JOIN borrowers as bor2 ON action_logs.object=bor2.borrowernumber
165         WHERE action_logs.module = 'members' 
166                 |;
167                 %filtermap = (
168                        user => 'borrowers.surname',
169                     surname => 'bor2.surname',
170                   firstname => 'bor2.firstname',
171                  cardnumber => 'bor2.cardnumber',
172                 );
173     } else {
174                 return 0;
175         }
176
177     if (@filters) {
178                 foreach my $filter (@filters) {
179                         my $tempname = $filter->{name}         or next;
180                         (grep {/^$tempname$/} keys %filtermap) or next;
181                         $filter->{value} =~ s/\*/%/g;
182                         $strsth .= " AND " . $filtermap{$tempname} . " LIKE " . $filter->{value};
183                 }
184         }
185     my $sth=$dbh->prepare($strsth);
186     $sth->execute;
187     my @results;
188     my $count;
189     my $hilighted=1;
190     while (my $data = $sth->fetchrow_hashref){
191         $data->{hilighted} = ($hilighted>0);
192         $data->{info} =~ s/\n/<br\/>/g;
193         $data->{day} = format_date($data->{timestamp});
194         push @results, $data;
195         $count++;
196         $hilighted = -$hilighted;
197     }
198     return ($count, \@results);
199 }
200
201 =item GetLogs
202
203 $logs = GetLogs($datefrom,$dateto,$user,\@modules,$action,$object,$info);
204
205 Return: 
206 C<$logs> is a ref to a hash which containts all columns from action_logs
207
208 =cut
209
210 sub GetLogs {
211     my $datefrom = shift;
212     my $dateto   = shift;
213     my $user     = shift;
214     my $modules   = shift;
215     my $action   = shift;
216     my $object   = shift;
217     my $info     = shift;
218    
219     my $iso_datefrom = C4::Dates->new($datefrom,C4::Context->preference("dateformat"))->output('iso');
220     my $iso_dateto = C4::Dates->new($dateto,C4::Context->preference("dateformat"))->output('iso');
221
222     my $dbh = C4::Context->dbh;
223     my $query = "
224         SELECT *
225         FROM   action_logs
226         WHERE 1
227     ";
228
229     my @parameters;
230     $query .= " AND DATE_FORMAT(timestamp, '%Y-%m-%d') >= \"".$iso_datefrom."\" " if $iso_datefrom;   #fix me - mysql specific
231     $query .= " AND DATE_FORMAT(timestamp, '%Y-%m-%d') <= \"".$iso_dateto."\" " if $iso_dateto;
232     if($user ne "") {
233         $query .= " AND user = ? ";
234         push(@parameters,$user);
235     }
236     if($modules && scalar(@$modules)) {
237         $query .= " AND module IN (".join(",",map {"?"} @$modules).") ";
238         push(@parameters,@$modules);
239     }
240     if($action && scalar(@$action)) {
241         $query .= " AND action IN (".join(",",map {"?"} @$action).") ";
242         push(@parameters,@$action);
243     }
244     if($object) {
245         $query .= " AND object = ? ";
246         push(@parameters,$object);
247     }
248     if($info) {
249         $query .= " AND info LIKE ? ";
250         push(@parameters,"%".$info."%");
251     }
252    
253     my $sth = $dbh->prepare($query);
254     $sth->execute(@parameters);
255     
256     my @logs;
257     while( my $row = $sth->fetchrow_hashref ) {
258         push @logs , $row;
259     }
260     return \@logs;
261 }
262
263 1;
264 __END__
265
266 =back
267
268 =head1 AUTHOR
269
270 Koha Development Team <http://koha-community.org/>
271
272 =cut