File Coverage

File:C4/Log.pm
Coverage:17.2%

linestmtbrancondsubtimecode
1package 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
22
22
22
21318
169
766
use strict;
25
22
22
22
374
150
1092
use warnings;
26
27
22
22
22
458
118
384
use C4::Context;
28
22
22
22
662
124
1719
use C4::Dates qw(format_date);
29
30
22
22
22
212
142
3128
use vars qw($VERSION @ISA @EXPORT);
31
32BEGIN {
33        # set the version for version checking
34
22
157
        $VERSION = 3.01;
35
22
252
        require Exporter;
36
22
486
        @ISA = qw(Exporter);
37
22
26079
        @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#'
68sub 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#'
98sub 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#'
123sub 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
195sub 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
2491;