Bug 16011: $VERSION - remove use vars $VERSION
[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     # 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($infos);
87
88 Convenience routine to add a record into action_logs table from a cron job.
89 Logs the path and name of the calling script plus the information privided by param $infos.
90
91 =cut
92
93 #'
94 sub cronlogaction {
95     my ($infos)=@_;
96     my $loginfo = (caller(0))[1];
97     $loginfo .= ' ' . $infos if $infos;
98     logaction( 'CRONJOBS', 'Run', undef, $loginfo ) if C4::Context->preference('CronjobLog');
99 }
100
101
102 =item GetLogStatus
103
104   $status = GetLogStatus;
105
106 C<$status> is a hasref like this example:
107     $hash = {
108         BorrowersLog   => 1,
109         CataloguingLog => 0,
110         IssueLog       => 0,
111         ...
112     }
113
114 =cut
115
116 #'
117 sub GetLogStatus {
118     my %hash;
119     $hash{BorrowersLog}    = C4::Context->preference("BorrowersLog");
120     $hash{CataloguingLog}  = C4::Context->preference("CataloguingLog");
121     $hash{IssueLog}        = C4::Context->preference("IssueLog");
122     $hash{ReturnLog}       = C4::Context->preference("ReturnLog");
123     $hash{SubscriptionLog} = C4::Context->preference("SubscriptionLog");
124     $hash{LetterLog}       = C4::Context->preference("LetterLog");
125     $hash{FinesLog}        = C4::Context->preference("FinesLog");
126     return \%hash;
127 }
128
129 =item displaylog
130
131   &displaylog($modulename, @filters);
132   $modulename is the name of the module on which the user wants to display logs
133   @filters is an optional table of hash containing :
134       - name : the name of the variable to filter
135     - value : the value of the filter.... May be with * joker
136
137 returns a table of hash containing who did what on which object at what time
138
139 =cut
140
141 #'
142 sub displaylog {
143   my ($modulename, @filters) = @_;
144     my $dbh = C4::Context->dbh;
145     my $strsth=qq|
146                 SELECT action_logs.timestamp, action_logs.action, action_logs.info,
147                                 borrowers.cardnumber, borrowers.surname, borrowers.firstname, borrowers.userid,
148                         biblio.biblionumber, biblio.title, biblio.author
149         FROM action_logs 
150                 LEFT JOIN borrowers ON borrowers.borrowernumber=action_logs.user 
151         LEFT JOIN  biblio   ON action_logs.object=biblio.biblionumber
152         WHERE action_logs.module = 'cataloguing' 
153         |;
154         my %filtermap = ();
155     if ($modulename eq "catalogue" or $modulename eq "acqui") {
156                 %filtermap = (
157                           user => 'borrowers.surname',
158                          title => 'biblio.title',
159                         author => 'biblio.author',
160                 );
161     } elsif ($modulename eq "members") {
162         $strsth=qq|
163                 SELECT action_logs.timestamp, action_logs.action, action_logs.info, 
164                         borrowers.cardnumber, borrowers.surname, borrowers.firstname, borrowers.userid,
165                         bor2.cardnumber, bor2.surname, bor2.firstname, bor2.userid
166         FROM action_logs 
167                 LEFT JOIN borrowers ON borrowers.borrowernumber=action_logs.user 
168                 LEFT JOIN borrowers as bor2 ON action_logs.object=bor2.borrowernumber
169         WHERE action_logs.module = 'members' 
170                 |;
171                 %filtermap = (
172                        user => 'borrowers.surname',
173                     surname => 'bor2.surname',
174                   firstname => 'bor2.firstname',
175                  cardnumber => 'bor2.cardnumber',
176                 );
177     } else {
178                 return 0;
179         }
180
181     if (@filters) {
182                 foreach my $filter (@filters) {
183                         my $tempname = $filter->{name}         or next;
184                         (grep {/^$tempname$/} keys %filtermap) or next;
185                         $filter->{value} =~ s/\*/%/g;
186                         $strsth .= " AND " . $filtermap{$tempname} . " LIKE " . $filter->{value};
187                 }
188         }
189     my $sth=$dbh->prepare($strsth);
190     $sth->execute;
191     my @results;
192     my $count;
193     my $hilighted=1;
194     while (my $data = $sth->fetchrow_hashref){
195         $data->{hilighted} = ($hilighted>0);
196         $data->{info} =~ s/\n/<br\/>/g;
197         $data->{day} = output_pref({ str => $data->{timestamp} });
198         push @results, $data;
199         $count++;
200         $hilighted = -$hilighted;
201     }
202     return ($count, \@results);
203 }
204
205 =item GetLogs
206
207 $logs = GetLogs($datefrom,$dateto,$user,\@modules,$action,$object,$info);
208
209 Return: 
210 C<$logs> is a ref to a hash which containts all columns from action_logs
211
212 =cut
213
214 sub GetLogs {
215     my $datefrom = shift;
216     my $dateto   = shift;
217     my $user     = shift;
218     my $modules  = shift;
219     my $action   = shift;
220     my $object   = shift;
221     my $info     = shift;
222
223     my $iso_datefrom = $datefrom ? output_pref({ dt => dt_from_string( $datefrom ), dateformat => 'iso', dateonly => 1 }) : undef;
224     my $iso_dateto = $dateto ? output_pref({ dt => dt_from_string( $dateto ), dateformat => 'iso', dateonly => 1 }) : undef;
225
226     $user ||= q{};
227
228     my $dbh   = C4::Context->dbh;
229     my $query = "
230         SELECT *
231         FROM   action_logs
232         WHERE 1
233     ";
234
235     my @parameters;
236     $query .=
237       " AND DATE_FORMAT(timestamp, '%Y-%m-%d') >= \"" . $iso_datefrom . "\" "
238       if $iso_datefrom;    #fix me - mysql specific
239     $query .=
240       " AND DATE_FORMAT(timestamp, '%Y-%m-%d') <= \"" . $iso_dateto . "\" "
241       if $iso_dateto;
242     if ( $user ne q{} ) {
243         $query .= " AND user = ? ";
244         push( @parameters, $user );
245     }
246     if ( $modules && scalar(@$modules) ) {
247         $query .=
248           " AND module IN (" . join( ",", map { "?" } @$modules ) . ") ";
249         push( @parameters, @$modules );
250     }
251     if ( $action && scalar(@$action) ) {
252         $query .= " AND action IN (" . join( ",", map { "?" } @$action ) . ") ";
253         push( @parameters, @$action );
254     }
255     if ($object) {
256         $query .= " AND object = ? ";
257         push( @parameters, $object );
258     }
259     if ($info) {
260         $query .= " AND info LIKE ? ";
261         push( @parameters, "%" . $info . "%" );
262     }
263
264     my $sth = $dbh->prepare($query);
265     $sth->execute(@parameters);
266
267     my @logs;
268     while ( my $row = $sth->fetchrow_hashref ) {
269         push @logs, $row;
270     }
271     return \@logs;
272 }
273
274 1;
275 __END__
276
277 =back
278
279 =head1 AUTHOR
280
281 Koha Development Team <http://koha-community.org/>
282
283 =cut