File: | C4/Log.pm |
Coverage: | 17.2% |
line | stmt | bran | cond | sub | time | code |
---|---|---|---|---|---|---|
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 under the | |||||
12 | # terms of the GNU General Public License as published by the Free Software | |||||
13 | # Foundation; either version 2 of the License, or (at your option) any later | |||||
14 | # version. | |||||
15 | # | |||||
16 | # Koha is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
17 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
18 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
19 | # | |||||
20 | # You should have received a copy of the GNU General Public License along | |||||
21 | # with Koha; if not, write to the Free Software Foundation, Inc., | |||||
22 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |||||
23 | ||||||
24 | 20 20 20 | 401 82 584 | use strict; | |||
25 | 20 20 20 | 202 113 1047 | use warnings; | |||
26 | ||||||
27 | 20 20 20 | 343 159 352 | use C4::Context; | |||
28 | 20 20 20 | 238 92 1455 | use C4::Dates qw(format_date); | |||
29 | ||||||
30 | 20 20 20 | 160 87 2329 | use vars qw($VERSION @ISA @EXPORT); | |||
31 | ||||||
32 | BEGIN { | |||||
33 | # set the version for version checking | |||||
34 | 20 | 81 | $VERSION = 3.01; | |||
35 | 20 | 154 | require Exporter; | |||
36 | 20 | 413 | @ISA = qw(Exporter); | |||
37 | 20 | 23999 | @EXPORT = qw(&logaction &GetLogStatus &displaylog &GetLogs); | |||
38 | } | |||||
39 | ||||||
40 - 65 | =head1 NAME C4::Log - Koha Log Facility functions =head1 SYNOPSIS use C4::Log; =head1 DESCRIPTION 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. =head1 FUNCTIONS =over 2 =item logaction &logaction($modulename, $actionname, $objectnumber, $infos); Adds a record into action_logs table to report the different changes upon the database. Each log entry includes the number of the user currently logged in. For batch jobs, which operate without authenticating a user and setting up a session, the user number is set to 0, which is the same as the superlibrarian's number. =cut | |||||
66 | ||||||
67 | #' | |||||
68 | sub logaction { | |||||
69 | 0 | 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 | 0 | my $userenv = C4::Context->userenv(); | ||||
75 | 0 | my $usernumber = (ref($userenv) eq 'HASH') ? $userenv->{'number'} : 0; | ||||
76 | ||||||
77 | 0 | my $dbh = C4::Context->dbh; | ||||
78 | 0 | my $sth=$dbh->prepare("Insert into action_logs (timestamp,user,module,action,object,info) values (now(),?,?,?,?,?)"); | ||||
79 | 0 | $sth->execute($usernumber,$modulename,$actionname,$objectnumber,$infos); | ||||
80 | 0 | $sth->finish; | ||||
81 | } | |||||
82 | ||||||
83 - 95 | =item GetLogStatus $status = GetLogStatus; C<$status> is a hasref like this example: $hash = { BorrowersLog => 1, CataloguingLog => 0, IssueLog => 0, ... } =cut | |||||
96 | ||||||
97 | #' | |||||
98 | sub GetLogStatus { | |||||
99 | 0 | my %hash; | ||||
100 | 0 | $hash{BorrowersLog} = C4::Context->preference("BorrowersLog"); | ||||
101 | 0 | $hash{CataloguingLog} = C4::Context->preference("CataloguingLog"); | ||||
102 | 0 | $hash{IssueLog} = C4::Context->preference("IssueLog"); | ||||
103 | 0 | $hash{ReturnLog} = C4::Context->preference("ReturnLog"); | ||||
104 | 0 | $hash{SubscriptionLog} = C4::Context->preference("SubscriptionLog"); | ||||
105 | 0 | $hash{LetterLog} = C4::Context->preference("LetterLog"); | ||||
106 | 0 | $hash{FinesLog} = C4::Context->preference("FinesLog"); | ||||
107 | 0 | return \%hash; | ||||
108 | } | |||||
109 | ||||||
110 - 120 | =item displaylog &displaylog($modulename, @filters); $modulename is the name of the module on which the user wants to display logs @filters is an optional table of hash containing : - name : the name of the variable to filter - value : the value of the filter.... May be with * joker returns a table of hash containing who did what on which object at what time =cut | |||||
121 | ||||||
122 | #' | |||||
123 | sub displaylog { | |||||
124 | 0 | my ($modulename, @filters) = @_; | ||||
125 | 0 | my $dbh = C4::Context->dbh; | ||||
126 | 0 | my $strsth=qq| | ||||
127 | SELECT action_logs.timestamp, action_logs.action, action_logs.info, | |||||
128 | borrowers.cardnumber, borrowers.surname, borrowers.firstname, borrowers.userid, | |||||
129 | biblio.biblionumber, biblio.title, biblio.author | |||||
130 | FROM action_logs | |||||
131 | LEFT JOIN borrowers ON borrowers.borrowernumber=action_logs.user | |||||
132 | LEFT JOIN biblio ON action_logs.object=biblio.biblionumber | |||||
133 | WHERE action_logs.module = 'cataloguing' | |||||
134 | |; | |||||
135 | 0 | my %filtermap = (); | ||||
136 | 0 | if ($modulename eq "catalogue" or $modulename eq "acqui") { | ||||
137 | 0 | %filtermap = ( | ||||
138 | user => 'borrowers.surname', | |||||
139 | title => 'biblio.title', | |||||
140 | author => 'biblio.author', | |||||
141 | ); | |||||
142 | } elsif ($modulename eq "members") { | |||||
143 | 0 | $strsth=qq| | ||||
144 | SELECT action_logs.timestamp, action_logs.action, action_logs.info, | |||||
145 | borrowers.cardnumber, borrowers.surname, borrowers.firstname, borrowers.userid, | |||||
146 | bor2.cardnumber, bor2.surname, bor2.firstname, bor2.userid | |||||
147 | FROM action_logs | |||||
148 | LEFT JOIN borrowers ON borrowers.borrowernumber=action_logs.user | |||||
149 | LEFT JOIN borrowers as bor2 ON action_logs.object=bor2.borrowernumber | |||||
150 | WHERE action_logs.module = 'members' | |||||
151 | |; | |||||
152 | 0 | %filtermap = ( | ||||
153 | user => 'borrowers.surname', | |||||
154 | surname => 'bor2.surname', | |||||
155 | firstname => 'bor2.firstname', | |||||
156 | cardnumber => 'bor2.cardnumber', | |||||
157 | ); | |||||
158 | } else { | |||||
159 | 0 | return 0; | ||||
160 | } | |||||
161 | ||||||
162 | 0 | if (@filters) { | ||||
163 | 0 | foreach my $filter (@filters) { | ||||
164 | 0 | my $tempname = $filter->{name} or next; | ||||
165 | 0 0 | (grep {/^$tempname$/} keys %filtermap) or next; | ||||
166 | 0 | $filter->{value} =~ s/\*/%/g; | ||||
167 | 0 | $strsth .= " AND " . $filtermap{$tempname} . " LIKE " . $filter->{value}; | ||||
168 | } | |||||
169 | } | |||||
170 | 0 | my $sth=$dbh->prepare($strsth); | ||||
171 | 0 | $sth->execute; | ||||
172 | 0 | my @results; | ||||
173 | 0 | my $count; | ||||
174 | 0 | my $hilighted=1; | ||||
175 | 0 | while (my $data = $sth->fetchrow_hashref){ | ||||
176 | 0 | $data->{hilighted} = ($hilighted>0); | ||||
177 | 0 | $data->{info} =~ s/\n/<br\/>/g; | ||||
178 | 0 | $data->{day} = format_date($data->{timestamp}); | ||||
179 | 0 | push @results, $data; | ||||
180 | 0 | $count++; | ||||
181 | 0 | $hilighted = -$hilighted; | ||||
182 | } | |||||
183 | 0 | return ($count, \@results); | ||||
184 | } | |||||
185 | ||||||
186 - 193 | =item GetLogs $logs = GetLogs($datefrom,$dateto,$user,\@modules,$action,$object,$info); Return: C<$logs> is a ref to a hash which containts all columns from action_logs =cut | |||||
194 | ||||||
195 | sub GetLogs { | |||||
196 | 0 | my $datefrom = shift; | ||||
197 | 0 | my $dateto = shift; | ||||
198 | 0 | my $user = shift; | ||||
199 | 0 | my $modules = shift; | ||||
200 | 0 | my $action = shift; | ||||
201 | 0 | my $object = shift; | ||||
202 | 0 | my $info = shift; | ||||
203 | ||||||
204 | 0 | my $iso_datefrom = C4::Dates->new($datefrom,C4::Context->preference("dateformat"))->output('iso'); | ||||
205 | 0 | my $iso_dateto = C4::Dates->new($dateto,C4::Context->preference("dateformat"))->output('iso'); | ||||
206 | ||||||
207 | 0 | my $dbh = C4::Context->dbh; | ||||
208 | 0 | my $query = " | ||||
209 | SELECT * | |||||
210 | FROM action_logs | |||||
211 | WHERE 1 | |||||
212 | "; | |||||
213 | ||||||
214 | 0 | my @parameters; | ||||
215 | 0 | $query .= " AND DATE_FORMAT(timestamp, '%Y-%m-%d') >= \"".$iso_datefrom."\" " if $iso_datefrom; #fix me - mysql specific | ||||
216 | 0 | $query .= " AND DATE_FORMAT(timestamp, '%Y-%m-%d') <= \"".$iso_dateto."\" " if $iso_dateto; | ||||
217 | 0 | if($user ne "") { | ||||
218 | 0 | $query .= " AND user = ? "; | ||||
219 | 0 | push(@parameters,$user); | ||||
220 | } | |||||
221 | 0 | if($modules && scalar(@$modules)) { | ||||
222 | 0 0 | $query .= " AND module IN (".join(",",map {"?"} @$modules).") "; | ||||
223 | 0 | push(@parameters,@$modules); | ||||
224 | } | |||||
225 | 0 | if($action && scalar(@$action)) { | ||||
226 | 0 0 | $query .= " AND action IN (".join(",",map {"?"} @$action).") "; | ||||
227 | 0 | push(@parameters,@$action); | ||||
228 | } | |||||
229 | 0 | if($object) { | ||||
230 | 0 | $query .= " AND object = ? "; | ||||
231 | 0 | push(@parameters,$object); | ||||
232 | } | |||||
233 | 0 | if($info) { | ||||
234 | 0 | $query .= " AND info LIKE ? "; | ||||
235 | 0 | push(@parameters,"%".$info."%"); | ||||
236 | } | |||||
237 | ||||||
238 | 0 | my $sth = $dbh->prepare($query); | ||||
239 | 0 | $sth->execute(@parameters); | ||||
240 | ||||||
241 | 0 | my @logs; | ||||
242 | 0 | while( my $row = $sth->fetchrow_hashref ) { | ||||
243 | 0 | $row->{$row->{module}} = 1; | ||||
244 | 0 | push @logs , $row; | ||||
245 | } | |||||
246 | 0 | return \@logs; | ||||
247 | } | |||||
248 | ||||||
249 | 1; |