Patch security hole in vestigial report.
[koha.git] / C4 / Branch.pm
1 package C4::Branch;
2
3 # This file is part of Koha.
4 #
5 # Koha is free software; you can redistribute it and/or modify it under the
6 # terms of the GNU General Public License as published by the Free Software
7 # Foundation; either version 2 of the License, or (at your option) any later
8 # version.
9 #
10 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License along with
15 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
16 # Suite 330, Boston, MA  02111-1307 USA
17
18
19 use strict;
20 require Exporter;
21 use C4::Context;
22 use C4::Koha;
23
24 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
25
26 BEGIN {
27         # set the version for version checking
28         $VERSION = 3.01;
29         @ISA    = qw(Exporter);
30         @EXPORT = qw(
31                 &GetBranchCategory
32                 &GetBranchName
33                 &GetBranch
34                 &GetBranches
35                 &GetBranchDetail
36                 &get_branchinfos_of
37                 &ModBranch
38                 &CheckBranchCategorycode
39                 &GetBranchInfo
40                 &GetCategoryTypes
41                 &GetBranchCategories
42                 &GetBranchesInCategory
43                 &ModBranchCategoryInfo
44                 &DelBranch
45                 &DelBranchCategory
46         );
47 }
48
49 =head1 NAME
50
51 C4::Branch - Koha branch module
52
53 =head1 SYNOPSIS
54
55 use C4::Branch;
56
57 =head1 DESCRIPTION
58
59 The functions in this module deal with branches.
60
61 =head1 FUNCTIONS
62
63 =head2 GetBranches
64
65   $branches = &GetBranches();
66   returns informations about ALL branches.
67   Create a branch selector with the following code
68   IndependantBranches Insensitive...
69   GetBranchInfo() returns the same information without the problems of this function 
70   (namespace collision, mainly).  You should probably use that, and replace GetBranches()
71   with GetBranchInfo() where you see it in the code.
72   
73 =head3 in PERL SCRIPT
74
75 my $branches = GetBranches;
76 my @branchloop;
77 foreach my $thisbranch (keys %$branches) {
78     my $selected = 1 if $thisbranch eq $branch;
79     my %row =(value => $thisbranch,
80                 selected => $selected,
81                 branchname => $branches->{$thisbranch}->{'branchname'},
82             );
83     push @branchloop, \%row;
84 }
85
86 =head3 in TEMPLATE
87             <select name="branch">
88                 <option value="">Default</option>
89             <!-- TMPL_LOOP name="branchloop" -->
90                 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="branchname" --></option>
91             <!-- /TMPL_LOOP -->
92             </select>
93
94 =cut
95
96 sub GetBranches {
97     my ($onlymine)=@_;
98     # returns a reference to a hash of references to ALL branches...
99     my %branches;
100     my $dbh = C4::Context->dbh;
101     my $sth;
102     my $query="SELECT * FROM branches";
103     my @bind_parameters;
104     if ($onlymine && C4::Context->userenv && C4::Context->userenv->{branch}){
105       $query .= ' WHERE branchcode = ? ';
106       push @bind_parameters, C4::Context->userenv->{branch};
107     }
108         $query.=" ORDER BY branchname";
109     $sth = $dbh->prepare($query);
110     $sth->execute( @bind_parameters );
111     while ( my $branch = $sth->fetchrow_hashref ) {
112         my $nsth =
113           $dbh->prepare(
114             "SELECT categorycode FROM branchrelations WHERE branchcode = ?");
115         $nsth->execute( $branch->{'branchcode'} );
116         while ( my ($cat) = $nsth->fetchrow_array ) {
117
118             # FIXME - This seems wrong. It ought to be
119             # $branch->{categorycodes}{$cat} = 1;
120             # otherwise, there's a namespace collision if there's a
121             # category with the same name as a field in the 'branches'
122             # table (i.e., don't create a category called "issuing").
123             # In addition, the current structure doesn't really allow
124             # you to list the categories that a branch belongs to:
125             # you'd have to list keys %$branch, and remove those keys
126             # that aren't fields in the "branches" table.
127          #   $branch->{$cat} = 1;
128             $branch->{category}{$cat} = 1;
129         }
130         $branches{ $branch->{'branchcode'} } = $branch;
131     }
132     return ( \%branches );
133 }
134
135 =head2 GetBranchName
136
137 =cut
138
139 sub GetBranchName {
140     my ($branchcode) = @_;
141     my $dbh = C4::Context->dbh;
142     my $sth;
143     $sth = $dbh->prepare("Select branchname from branches where branchcode=?");
144     $sth->execute($branchcode);
145     my $branchname = $sth->fetchrow_array;
146     $sth->finish;
147     return ($branchname);
148 }
149
150 =head2 ModBranch
151
152 &ModBranch($newvalue);
153
154 This function modify an existing branches.
155
156 C<$newvalue> is a ref to an array wich is containt all the column from branches table.
157
158 =cut
159
160 sub ModBranch {
161     my ($data) = @_;
162     
163     my $dbh    = C4::Context->dbh;
164     if ($data->{add}) {
165         my $query  = "
166             INSERT INTO branches
167             (branchcode,branchname,branchaddress1,
168             branchaddress2,branchaddress3,branchphone,
169             branchfax,branchemail,branchip,branchprinter)
170             VALUES (?,?,?,?,?,?,?,?,?,?)
171         ";
172         my $sth    = $dbh->prepare($query);
173         $sth->execute(
174             $data->{'branchcode'},       $data->{'branchname'},
175             $data->{'branchaddress1'},   $data->{'branchaddress2'},
176             $data->{'branchaddress3'},   $data->{'branchphone'},
177             $data->{'branchfax'},        $data->{'branchemail'},
178             $data->{'branchip'},         $data->{'branchprinter'},
179         );
180     } else {
181         my $query  = "
182             UPDATE branches
183             SET branchname=?,branchaddress1=?,
184                 branchaddress2=?,branchaddress3=?,branchphone=?,
185                 branchfax=?,branchemail=?,branchip=?,branchprinter=?
186             WHERE branchcode=?
187         ";
188         my $sth    = $dbh->prepare($query);
189         $sth->execute(
190             $data->{'branchname'},
191             $data->{'branchaddress1'},   $data->{'branchaddress2'},
192             $data->{'branchaddress3'},   $data->{'branchphone'},
193             $data->{'branchfax'},        $data->{'branchemail'},
194             $data->{'branchip'},         $data->{'branchprinter'},
195             $data->{'branchcode'},
196         );
197     }
198     # sort out the categories....
199     my @checkedcats;
200     my $cats = GetBranchCategory();
201     foreach my $cat (@$cats) {
202         my $code = $cat->{'categorycode'};
203         if ( $data->{$code} ) {
204             push( @checkedcats, $code );
205         }
206     }
207     my $branchcode = uc( $data->{'branchcode'} );
208     my $branch     = GetBranchInfo($branchcode);
209     $branch = $branch->[0];
210     my $branchcats = $branch->{'categories'};
211     my @addcats;
212     my @removecats;
213     foreach my $bcat (@$branchcats) {
214
215         unless ( grep { /^$bcat$/ } @checkedcats ) {
216             push( @removecats, $bcat );
217         }
218     }
219     foreach my $ccat (@checkedcats) {
220         unless ( grep { /^$ccat$/ } @$branchcats ) {
221             push( @addcats, $ccat );
222         }
223     }
224     foreach my $cat (@addcats) {
225         my $sth =
226           $dbh->prepare(
227 "insert into branchrelations (branchcode, categorycode) values(?, ?)"
228           );
229         $sth->execute( $branchcode, $cat );
230         $sth->finish;
231     }
232     foreach my $cat (@removecats) {
233         my $sth =
234           $dbh->prepare(
235             "delete from branchrelations where branchcode=? and categorycode=?"
236           );
237         $sth->execute( $branchcode, $cat );
238         $sth->finish;
239     }
240 }
241
242 =head2 GetBranchCategory
243
244 $results = GetBranchCategory($categorycode);
245
246 C<$results> is an ref to an array.
247
248 =cut
249
250 sub GetBranchCategory {
251
252     # returns a reference to an array of hashes containing branches,
253     my ($catcode) = @_;
254     my $dbh = C4::Context->dbh;
255     my $sth;
256
257     #    print DEBUG "GetBranchCategory: entry: catcode=".cvs($catcode)."\n";
258     if ($catcode) {
259         $sth =
260           $dbh->prepare(
261             "select * from branchcategories where categorycode = ?");
262         $sth->execute($catcode);
263     }
264     else {
265         $sth = $dbh->prepare("Select * from branchcategories");
266         $sth->execute();
267     }
268     my @results;
269     while ( my $data = $sth->fetchrow_hashref ) {
270         push( @results, $data );
271     }
272     $sth->finish;
273
274     #    print DEBUG "GetBranchCategory: exit: returning ".cvs(\@results)."\n";
275     return \@results;
276 }
277
278 =head2 GetBranchCategories
279
280   my $categories = GetBranchCategories($branchcode,$categorytype);
281
282 Returns a list ref of anon hashrefs with keys eq columns of branchcategories table,
283 i.e. categorycode, categorydescription, categorytype, categoryname.
284 if $branchcode and/or $categorytype are passed, limit set to categories that
285 $branchcode is a member of , and to $categorytype.
286
287 =cut
288
289 sub GetBranchCategories {
290     my ($branchcode,$categorytype) = @_;
291         my $dbh = C4::Context->dbh();
292         my $query = "SELECT c.* FROM branchcategories c";
293         my (@where, @bind);
294         if($branchcode) {
295                 $query .= ",branchrelations r, branches b ";
296                 push @where, "c.categorycode=r.categorycode and r.branchcode=? ";  
297                 push @bind , $branchcode;
298         }
299         if ($categorytype) {
300                 push @where, " c.categorytype=? ";
301                 push @bind, $categorytype;
302         }
303         $query .= " where " . join(" and ", @where) if(@where);
304         $query .= " order by categorytype,c.categorycode";
305         my $sth=$dbh->prepare( $query);
306         $sth->execute(@bind);
307         
308         my $branchcats = $sth->fetchall_arrayref({});
309         $sth->finish();
310         return( $branchcats );
311 }
312
313 =head2 GetCategoryTypes
314
315 $categorytypes = GetCategoryTypes;
316 returns a list of category types.
317 Currently these types are HARDCODED.
318 type: 'searchdomain' defines a group of agencies that the calling library may search in.
319 Other usage of agency categories falls under type: 'properties'.
320         to allow for other uses of categories.
321 The searchdomain bit may be better implemented as a separate module, but
322 the categories were already here, and minimally used.
323 =cut
324
325         #TODO  manage category types.  rename possibly to 'agency domains' ? as borrowergroups are called categories.
326 sub GetCategoryTypes() {
327         return ( 'searchdomain','properties');
328 }
329
330 =head2 GetBranch
331
332 $branch = GetBranch( $query, $branches );
333
334 =cut
335
336 sub GetBranch ($$) {
337     my ( $query, $branches ) = @_;    # get branch for this query from branches
338     my $branch = $query->param('branch');
339     my %cookie = $query->cookie('userenv');
340     ($branch)                || ($branch = $cookie{'branchname'});
341     ( $branches->{$branch} ) || ( $branch = ( keys %$branches )[0] );
342     return $branch;
343 }
344
345 =head2 GetBranchDetail
346
347   $branchname = &GetBranchDetail($branchcode);
348
349 Given the branch code, the function returns the corresponding
350 branch name for a comprehensive information display
351
352 =cut
353
354 sub GetBranchDetail {
355     my ($branchcode) = @_;
356     my $dbh = C4::Context->dbh;
357     my $sth = $dbh->prepare("SELECT * FROM branches WHERE branchcode = ?");
358     $sth->execute($branchcode);
359     my $branchname = $sth->fetchrow_hashref();
360     $sth->finish();
361     return $branchname;
362 }
363
364 =head2 get_branchinfos_of
365
366   my $branchinfos_of = get_branchinfos_of(@branchcodes);
367
368 Associates a list of branchcodes to the information of the branch, taken in
369 branches table.
370
371 Returns a href where keys are branchcodes and values are href where keys are
372 branch information key.
373
374   print 'branchname is ', $branchinfos_of->{$code}->{branchname};
375
376 =cut
377
378 sub get_branchinfos_of {
379     my @branchcodes = @_;
380
381     my $query = '
382     SELECT branchcode,
383        branchname
384     FROM branches
385     WHERE branchcode IN ('
386       . join( ',', map( { "'" . $_ . "'" } @branchcodes ) ) . ')
387 ';
388     return C4::Koha::get_infos_of( $query, 'branchcode' );
389 }
390
391
392 =head2 GetBranchesInCategory
393
394   my $branches = GetBranchesInCategory($categorycode);
395
396 Returns a href:  keys %$branches eq (branchcode,branchname) .
397
398 =cut
399
400 sub GetBranchesInCategory($) {
401     my ($categorycode) = @_;
402         my @branches;
403         my $dbh = C4::Context->dbh();
404         my $sth=$dbh->prepare( "SELECT b.branchcode FROM branchrelations r, branches b 
405                                                         where r.branchcode=b.branchcode and r.categorycode=?");
406     $sth->execute($categorycode);
407         while (my $branch = $sth->fetchrow) {
408                 push @branches, $branch;
409         }
410         $sth->finish();
411         return( \@branches );
412 }
413
414 =head2 GetBranchInfo
415
416 $results = GetBranchInfo($branchcode);
417
418 returns C<$results>, a reference to an array of hashes containing branches.
419 if $branchcode, just this branch, with associated categories.
420 if ! $branchcode && $categorytype, all branches in the category.
421 =cut
422
423 sub GetBranchInfo {
424     my ($branchcode,$categorytype) = @_;
425     my $dbh = C4::Context->dbh;
426     my $sth;
427
428
429         if ($branchcode) {
430         $sth =
431           $dbh->prepare(
432             "Select * from branches where branchcode = ? order by branchcode");
433         $sth->execute($branchcode);
434     }
435     else {
436         $sth = $dbh->prepare("Select * from branches order by branchcode");
437         $sth->execute();
438     }
439     my @results;
440     while ( my $data = $sth->fetchrow_hashref ) {
441                 my @bind = ($data->{'branchcode'});
442         my $query= "select r.categorycode from branchrelations r";
443                 $query .= ", branchcategories c " if($categorytype);
444                 $query .= " where  branchcode=? ";
445                 if($categorytype) { 
446                         $query .= " and c.categorytype=? and r.categorycode=c.categorycode";
447                         push @bind, $categorytype;
448                 }
449         my $nsth=$dbh->prepare($query);
450                 $nsth->execute( @bind );
451         my @cats = ();
452         while ( my ($cat) = $nsth->fetchrow_array ) {
453             push( @cats, $cat );
454         }
455         $nsth->finish;
456         $data->{'categories'} = \@cats;
457         push( @results, $data );
458     }
459     $sth->finish;
460     return \@results;
461 }
462
463 =head2 DelBranch
464
465 &DelBranch($branchcode);
466
467 =cut
468
469 sub DelBranch {
470     my ($branchcode) = @_;
471     my $dbh = C4::Context->dbh;
472     my $sth = $dbh->prepare("delete from branches where branchcode = ?");
473     $sth->execute($branchcode);
474     $sth->finish;
475 }
476
477 =head2 ModBranchCategoryInfo
478
479 &ModBranchCategoryInfo($data);
480 sets the data from the editbranch form, and writes to the database...
481
482 =cut
483
484 sub ModBranchCategoryInfo {
485     my ($data) = @_;
486     my $dbh    = C4::Context->dbh;
487         if ($data->{'add'}){
488                 # we are doing an insert
489                 my $sth   = $dbh->prepare("INSERT INTO branchcategories (categorycode,categoryname,codedescription,categorytype) VALUES (?,?,?,?)");
490                 $sth->execute(uc( $data->{'categorycode'} ),$data->{'categoryname'}, $data->{'codedescription'},$data->{'categorytype'} );
491                 $sth->finish();         
492         }
493         else {
494                 # modifying
495                 my $sth = $dbh->prepare("UPDATE branchcategories SET categoryname=?,codedescription=?,categorytype=? WHERE categorycode=?");
496                 $sth->execute($data->{'categoryname'}, $data->{'codedescription'},$data->{'categorytype'},uc( $data->{'categorycode'} ) );
497                 $sth->finish();
498         }
499 }
500
501 =head2 DeleteBranchCategory
502
503 DeleteBranchCategory($categorycode);
504
505 =cut
506
507 sub DelBranchCategory {
508     my ($categorycode) = @_;
509     my $dbh = C4::Context->dbh;
510     my $sth = $dbh->prepare("delete from branchcategories where categorycode = ?");
511     $sth->execute($categorycode);
512     $sth->finish;
513 }
514
515 =head2 CheckBranchCategorycode
516
517 $number_rows_affected = CheckBranchCategorycode($categorycode);
518
519 =cut
520
521 sub CheckBranchCategorycode {
522
523     # check to see if the branchcode is being used in the database somewhere....
524     my ($categorycode) = @_;
525     my $dbh            = C4::Context->dbh;
526     my $sth            =
527       $dbh->prepare(
528         "select count(*) from branchrelations where categorycode=?");
529     $sth->execute($categorycode);
530     my ($total) = $sth->fetchrow_array;
531     return $total;
532 }
533
534 1;
535 __END__
536
537 =head1 AUTHOR
538
539 Koha Developement team <info@koha.org>
540
541 =cut