| Filename | /mnt/catalyst/koha/C4/Log.pm |
| Statements | Executed 15 statements in 855µs |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 454µs | 466µs | C4::Log::BEGIN@24 |
| 1 | 1 | 1 | 10µs | 45µs | C4::Log::BEGIN@30 |
| 1 | 1 | 1 | 10µs | 10µs | C4::Log::BEGIN@32 |
| 1 | 1 | 1 | 8µs | 15µs | C4::Log::BEGIN@25 |
| 1 | 1 | 1 | 8µs | 11µs | C4::Log::BEGIN@27 |
| 1 | 1 | 1 | 6µs | 27µs | C4::Log::BEGIN@28 |
| 0 | 0 | 0 | 0s | 0s | C4::Log::GetLogStatus |
| 0 | 0 | 0 | 0s | 0s | C4::Log::GetLogs |
| 0 | 0 | 0 | 0s | 0s | C4::Log::displaylog |
| 0 | 0 | 0 | 0s | 0s | C4::Log::logaction |
| Line | State ments |
Time on line |
Calls | Time in subs |
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 | 2 | 27µs | 2 | 479µs | # spent 466µs (454+12) within C4::Log::BEGIN@24 which was called:
# once (454µs+12µs) by C4::Members::BEGIN@29 at line 24 # spent 466µs making 1 call to C4::Log::BEGIN@24
# spent 12µs making 1 call to strict::import |
| 25 | 2 | 21µs | 2 | 22µs | # spent 15µs (8+7) within C4::Log::BEGIN@25 which was called:
# once (8µs+7µs) by C4::Members::BEGIN@29 at line 25 # spent 15µs making 1 call to C4::Log::BEGIN@25
# spent 7µs making 1 call to warnings::import |
| 26 | |||||
| 27 | 2 | 22µs | 2 | 13µs | # spent 11µs (8+3) within C4::Log::BEGIN@27 which was called:
# once (8µs+3µs) by C4::Members::BEGIN@29 at line 27 # spent 11µs making 1 call to C4::Log::BEGIN@27
# spent 3µs making 1 call to C4::Context::import |
| 28 | 2 | 23µs | 2 | 47µs | # spent 27µs (6+20) within C4::Log::BEGIN@28 which was called:
# once (6µs+20µs) by C4::Members::BEGIN@29 at line 28 # spent 27µs making 1 call to C4::Log::BEGIN@28
# spent 20µs making 1 call to Exporter::import |
| 29 | |||||
| 30 | 2 | 44µs | 2 | 80µs | # spent 45µs (10+35) within C4::Log::BEGIN@30 which was called:
# once (10µs+35µs) by C4::Members::BEGIN@29 at line 30 # spent 45µs making 1 call to C4::Log::BEGIN@30
# spent 35µs making 1 call to vars::import |
| 31 | |||||
| 32 | # spent 10µs within C4::Log::BEGIN@32 which was called:
# once (10µs+0s) by C4::Members::BEGIN@29 at line 38 | ||||
| 33 | # set the version for version checking | ||||
| 34 | 1 | 800ns | $VERSION = 3.07.00.049; | ||
| 35 | 1 | 600ns | require Exporter; | ||
| 36 | 1 | 5µs | @ISA = qw(Exporter); | ||
| 37 | 1 | 4µs | @EXPORT = qw(&logaction &GetLogStatus &displaylog &GetLogs); | ||
| 38 | 1 | 705µs | 1 | 10µs | } # spent 10µs making 1 call to C4::Log::BEGIN@32 |
| 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 GetLogStatus | ||||
| 85 | |||||
| 86 | $status = GetLogStatus; | ||||
| 87 | |||||
| 88 | C<$status> is a hasref like this example: | ||||
| 89 | $hash = { | ||||
| 90 | BorrowersLog => 1, | ||||
| 91 | CataloguingLog => 0, | ||||
| 92 | IssueLog => 0, | ||||
| 93 | ... | ||||
| 94 | } | ||||
| 95 | |||||
| 96 | =cut | ||||
| 97 | |||||
| 98 | #' | ||||
| 99 | sub GetLogStatus { | ||||
| 100 | my %hash; | ||||
| 101 | $hash{BorrowersLog} = C4::Context->preference("BorrowersLog"); | ||||
| 102 | $hash{CataloguingLog} = C4::Context->preference("CataloguingLog"); | ||||
| 103 | $hash{IssueLog} = C4::Context->preference("IssueLog"); | ||||
| 104 | $hash{ReturnLog} = C4::Context->preference("ReturnLog"); | ||||
| 105 | $hash{SubscriptionLog} = C4::Context->preference("SubscriptionLog"); | ||||
| 106 | $hash{LetterLog} = C4::Context->preference("LetterLog"); | ||||
| 107 | $hash{FinesLog} = C4::Context->preference("FinesLog"); | ||||
| 108 | return \%hash; | ||||
| 109 | } | ||||
| 110 | |||||
| 111 | =item displaylog | ||||
| 112 | |||||
| 113 | &displaylog($modulename, @filters); | ||||
| 114 | $modulename is the name of the module on which the user wants to display logs | ||||
| 115 | @filters is an optional table of hash containing : | ||||
| 116 | - name : the name of the variable to filter | ||||
| 117 | - value : the value of the filter.... May be with * joker | ||||
| 118 | |||||
| 119 | returns a table of hash containing who did what on which object at what time | ||||
| 120 | |||||
| 121 | =cut | ||||
| 122 | |||||
| 123 | #' | ||||
| 124 | sub displaylog { | ||||
| 125 | my ($modulename, @filters) = @_; | ||||
| 126 | my $dbh = C4::Context->dbh; | ||||
| 127 | my $strsth=qq| | ||||
| 128 | SELECT action_logs.timestamp, action_logs.action, action_logs.info, | ||||
| 129 | borrowers.cardnumber, borrowers.surname, borrowers.firstname, borrowers.userid, | ||||
| 130 | biblio.biblionumber, biblio.title, biblio.author | ||||
| 131 | FROM action_logs | ||||
| 132 | LEFT JOIN borrowers ON borrowers.borrowernumber=action_logs.user | ||||
| 133 | LEFT JOIN biblio ON action_logs.object=biblio.biblionumber | ||||
| 134 | WHERE action_logs.module = 'cataloguing' | ||||
| 135 | |; | ||||
| 136 | my %filtermap = (); | ||||
| 137 | if ($modulename eq "catalogue" or $modulename eq "acqui") { | ||||
| 138 | %filtermap = ( | ||||
| 139 | user => 'borrowers.surname', | ||||
| 140 | title => 'biblio.title', | ||||
| 141 | author => 'biblio.author', | ||||
| 142 | ); | ||||
| 143 | } elsif ($modulename eq "members") { | ||||
| 144 | $strsth=qq| | ||||
| 145 | SELECT action_logs.timestamp, action_logs.action, action_logs.info, | ||||
| 146 | borrowers.cardnumber, borrowers.surname, borrowers.firstname, borrowers.userid, | ||||
| 147 | bor2.cardnumber, bor2.surname, bor2.firstname, bor2.userid | ||||
| 148 | FROM action_logs | ||||
| 149 | LEFT JOIN borrowers ON borrowers.borrowernumber=action_logs.user | ||||
| 150 | LEFT JOIN borrowers as bor2 ON action_logs.object=bor2.borrowernumber | ||||
| 151 | WHERE action_logs.module = 'members' | ||||
| 152 | |; | ||||
| 153 | %filtermap = ( | ||||
| 154 | user => 'borrowers.surname', | ||||
| 155 | surname => 'bor2.surname', | ||||
| 156 | firstname => 'bor2.firstname', | ||||
| 157 | cardnumber => 'bor2.cardnumber', | ||||
| 158 | ); | ||||
| 159 | } else { | ||||
| 160 | return 0; | ||||
| 161 | } | ||||
| 162 | |||||
| 163 | if (@filters) { | ||||
| 164 | foreach my $filter (@filters) { | ||||
| 165 | my $tempname = $filter->{name} or next; | ||||
| 166 | (grep {/^$tempname$/} keys %filtermap) or next; | ||||
| 167 | $filter->{value} =~ s/\*/%/g; | ||||
| 168 | $strsth .= " AND " . $filtermap{$tempname} . " LIKE " . $filter->{value}; | ||||
| 169 | } | ||||
| 170 | } | ||||
| 171 | my $sth=$dbh->prepare($strsth); | ||||
| 172 | $sth->execute; | ||||
| 173 | my @results; | ||||
| 174 | my $count; | ||||
| 175 | my $hilighted=1; | ||||
| 176 | while (my $data = $sth->fetchrow_hashref){ | ||||
| 177 | $data->{hilighted} = ($hilighted>0); | ||||
| 178 | $data->{info} =~ s/\n/<br\/>/g; | ||||
| 179 | $data->{day} = format_date($data->{timestamp}); | ||||
| 180 | push @results, $data; | ||||
| 181 | $count++; | ||||
| 182 | $hilighted = -$hilighted; | ||||
| 183 | } | ||||
| 184 | return ($count, \@results); | ||||
| 185 | } | ||||
| 186 | |||||
| 187 | =item GetLogs | ||||
| 188 | |||||
| 189 | $logs = GetLogs($datefrom,$dateto,$user,\@modules,$action,$object,$info); | ||||
| 190 | |||||
| 191 | Return: | ||||
| 192 | C<$logs> is a ref to a hash which containts all columns from action_logs | ||||
| 193 | |||||
| 194 | =cut | ||||
| 195 | |||||
| 196 | sub GetLogs { | ||||
| 197 | my $datefrom = shift; | ||||
| 198 | my $dateto = shift; | ||||
| 199 | my $user = shift; | ||||
| 200 | my $modules = shift; | ||||
| 201 | my $action = shift; | ||||
| 202 | my $object = shift; | ||||
| 203 | my $info = shift; | ||||
| 204 | |||||
| 205 | my $iso_datefrom = C4::Dates->new($datefrom,C4::Context->preference("dateformat"))->output('iso'); | ||||
| 206 | my $iso_dateto = C4::Dates->new($dateto,C4::Context->preference("dateformat"))->output('iso'); | ||||
| 207 | |||||
| 208 | my $dbh = C4::Context->dbh; | ||||
| 209 | my $query = " | ||||
| 210 | SELECT * | ||||
| 211 | FROM action_logs | ||||
| 212 | WHERE 1 | ||||
| 213 | "; | ||||
| 214 | |||||
| 215 | my @parameters; | ||||
| 216 | $query .= " AND DATE_FORMAT(timestamp, '%Y-%m-%d') >= \"".$iso_datefrom."\" " if $iso_datefrom; #fix me - mysql specific | ||||
| 217 | $query .= " AND DATE_FORMAT(timestamp, '%Y-%m-%d') <= \"".$iso_dateto."\" " if $iso_dateto; | ||||
| 218 | if($user ne "") { | ||||
| 219 | $query .= " AND user = ? "; | ||||
| 220 | push(@parameters,$user); | ||||
| 221 | } | ||||
| 222 | if($modules && scalar(@$modules)) { | ||||
| 223 | $query .= " AND module IN (".join(",",map {"?"} @$modules).") "; | ||||
| 224 | push(@parameters,@$modules); | ||||
| 225 | } | ||||
| 226 | if($action && scalar(@$action)) { | ||||
| 227 | $query .= " AND action IN (".join(",",map {"?"} @$action).") "; | ||||
| 228 | push(@parameters,@$action); | ||||
| 229 | } | ||||
| 230 | if($object) { | ||||
| 231 | $query .= " AND object = ? "; | ||||
| 232 | push(@parameters,$object); | ||||
| 233 | } | ||||
| 234 | if($info) { | ||||
| 235 | $query .= " AND info LIKE ? "; | ||||
| 236 | push(@parameters,"%".$info."%"); | ||||
| 237 | } | ||||
| 238 | |||||
| 239 | my $sth = $dbh->prepare($query); | ||||
| 240 | $sth->execute(@parameters); | ||||
| 241 | |||||
| 242 | my @logs; | ||||
| 243 | while( my $row = $sth->fetchrow_hashref ) { | ||||
| 244 | $row->{$row->{module}} = 1; | ||||
| 245 | push @logs , $row; | ||||
| 246 | } | ||||
| 247 | return \@logs; | ||||
| 248 | } | ||||
| 249 | |||||
| 250 | 1 | 2µs | 1; | ||
| 251 | __END__ |