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