removing all useless %env / $env
[koha.git] / C4 / Koha.pm
1 package C4::Koha;
2
3 # Copyright 2000-2002 Katipo Communications
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
10 # version.
11 #
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License along with
17 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
18 # Suite 330, Boston, MA  02111-1307 USA
19
20 # $Id$
21
22 use strict;
23 require Exporter;
24 use C4::Context;
25 use C4::Output;
26 use vars qw($VERSION @ISA @EXPORT);
27
28 $VERSION = do { my @v = '$Revision$' =~ /\d+/g; shift(@v) . "." . join( "_", map { sprintf "%03d", $_ } @v ); };
29
30 =head1 NAME
31
32 C4::Koha - Perl Module containing convenience functions for Koha scripts
33
34 =head1 SYNOPSIS
35
36   use C4::Koha;
37
38
39 =head1 DESCRIPTION
40
41 Koha.pm provides many functions for Koha scripts.
42
43 =head1 FUNCTIONS
44
45 =over 2
46
47 =cut
48
49 @ISA    = qw(Exporter);
50 @EXPORT = qw(
51   &slashifyDate
52   &DisplayISBN
53   &subfield_is_koha_internal_p
54   &GetPrinters &GetPrinter
55   &GetItemTypes &getitemtypeinfo
56   &GetCcodes
57   &GetAuthItemlost
58   &GetAuthItembinding
59   &get_itemtypeinfos_of
60   &getframeworks &getframeworkinfo
61   &getauthtypes &getauthtype
62   &getallthemes
63   &getFacets
64   &displaySortby
65   &displayIndexes
66   &displaySubtypesLimit
67   &displayLimitTypes
68   &displayServers
69   &getnbpages
70   &getitemtypeimagesrcfromurl
71   &get_infos_of
72   &get_notforloan_label_of
73   &getitemtypeimagedir
74   &getitemtypeimagesrc
75   &GetAuthorisedValues
76   &FixEncoding
77   &GetKohaAuthorisedValues
78   $DEBUG
79   );
80
81 my $DEBUG = 0;
82
83 =head2 slashifyDate
84
85   $slash_date = &slashifyDate($dash_date);
86
87 Takes a string of the form "DD-MM-YYYY" (or anything separated by
88 dashes), converts it to the form "YYYY/MM/DD", and returns the result.
89
90 =cut
91
92 sub slashifyDate {
93
94     # accepts a date of the form xx-xx-xx[xx] and returns it in the
95     # form xx/xx/xx[xx]
96     my @dateOut = split( '-', shift );
97     return ("$dateOut[2]/$dateOut[1]/$dateOut[0]");
98 }
99
100
101 =head2 DisplayISBN
102
103 my $string = DisplayISBN( $isbn );
104
105 =cut
106
107 sub DisplayISBN {
108     my ($isbn) = @_;
109     my $seg1;
110     if ( substr( $isbn, 0, 1 ) <= 7 ) {
111         $seg1 = substr( $isbn, 0, 1 );
112     }
113     elsif ( substr( $isbn, 0, 2 ) <= 94 ) {
114         $seg1 = substr( $isbn, 0, 2 );
115     }
116     elsif ( substr( $isbn, 0, 3 ) <= 995 ) {
117         $seg1 = substr( $isbn, 0, 3 );
118     }
119     elsif ( substr( $isbn, 0, 4 ) <= 9989 ) {
120         $seg1 = substr( $isbn, 0, 4 );
121     }
122     else {
123         $seg1 = substr( $isbn, 0, 5 );
124     }
125     my $x = substr( $isbn, length($seg1) );
126     my $seg2;
127     if ( substr( $x, 0, 2 ) <= 19 ) {
128
129         #         if(sTmp2 < 10) sTmp2 = "0" sTmp2;
130         $seg2 = substr( $x, 0, 2 );
131     }
132     elsif ( substr( $x, 0, 3 ) <= 699 ) {
133         $seg2 = substr( $x, 0, 3 );
134     }
135     elsif ( substr( $x, 0, 4 ) <= 8399 ) {
136         $seg2 = substr( $x, 0, 4 );
137     }
138     elsif ( substr( $x, 0, 5 ) <= 89999 ) {
139         $seg2 = substr( $x, 0, 5 );
140     }
141     elsif ( substr( $x, 0, 6 ) <= 9499999 ) {
142         $seg2 = substr( $x, 0, 6 );
143     }
144     else {
145         $seg2 = substr( $x, 0, 7 );
146     }
147     my $seg3 = substr( $x, length($seg2) );
148     $seg3 = substr( $seg3, 0, length($seg3) - 1 );
149     my $seg4 = substr( $x, -1, 1 );
150     return "$seg1-$seg2-$seg3-$seg4";
151 }
152
153 # FIXME.. this should be moved to a MARC-specific module
154 sub subfield_is_koha_internal_p ($) {
155     my ($subfield) = @_;
156
157     # We could match on 'lib' and 'tab' (and 'mandatory', & more to come!)
158     # But real MARC subfields are always single-character
159     # so it really is safer just to check the length
160
161     return length $subfield != 1;
162 }
163
164 =head2 GetItemTypes
165
166   $itemtypes = &GetItemTypes();
167
168 Returns information about existing itemtypes.
169
170 build a HTML select with the following code :
171
172 =head3 in PERL SCRIPT
173
174 my $itemtypes = GetItemTypes;
175 my @itemtypesloop;
176 foreach my $thisitemtype (sort keys %$itemtypes) {
177     my $selected = 1 if $thisitemtype eq $itemtype;
178     my %row =(value => $thisitemtype,
179                 selected => $selected,
180                 description => $itemtypes->{$thisitemtype}->{'description'},
181             );
182     push @itemtypesloop, \%row;
183 }
184 $template->param(itemtypeloop => \@itemtypesloop);
185
186 =head3 in TEMPLATE
187
188 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
189     <select name="itemtype">
190         <option value="">Default</option>
191     <!-- TMPL_LOOP name="itemtypeloop" -->
192         <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="description" --></option>
193     <!-- /TMPL_LOOP -->
194     </select>
195     <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
196     <input type="submit" value="OK" class="button">
197 </form>
198
199
200 =cut
201
202 sub GetItemTypes {
203
204     # returns a reference to a hash of references to branches...
205     my %itemtypes;
206     my $dbh   = C4::Context->dbh;
207     my $query = qq|
208         SELECT *
209         FROM   itemtypes
210     |;
211     my $sth = $dbh->prepare($query);
212     $sth->execute;
213     while ( my $IT = $sth->fetchrow_hashref ) {
214         $itemtypes{ $IT->{'itemtype'} } = $IT;
215     }
216     return ( \%itemtypes );
217 }
218
219 sub get_itemtypeinfos_of {
220     my @itemtypes = @_;
221
222     my $query = '
223 SELECT itemtype,
224        description,
225        notforloan
226   FROM itemtypes
227   WHERE itemtype IN (' . join( ',', map( { "'" . $_ . "'" } @itemtypes ) ) . ')
228 ';
229
230     return get_infos_of( $query, 'itemtype' );
231 }
232
233 # this is temporary until we separate collection codes and item types
234 sub GetCcodes {
235     my $count = 0;
236     my @results;
237     my $dbh = C4::Context->dbh;
238     my $sth =
239       $dbh->prepare(
240         "SELECT * FROM authorised_values ORDER BY authorised_value");
241     $sth->execute;
242     while ( my $data = $sth->fetchrow_hashref ) {
243         if ( $data->{category} eq "CCODE" ) {
244             $count++;
245             $results[$count] = $data;
246
247             #warn "data: $data";
248         }
249     }
250     $sth->finish;
251     return ( $count, @results );
252 }
253
254 =head2
255
256 grab itemlost authorized values
257
258 =cut
259
260 sub GetAuthItemlost {
261     my $itemlost = shift;
262     my $count    = 0;
263     my @results;
264     my $dbh = C4::Context->dbh;
265     my $sth =
266       $dbh->prepare(
267         "SELECT * FROM authorised_values ORDER BY authorised_value");
268     $sth->execute;
269     while ( my $data = $sth->fetchrow_hashref ) {
270         if ( $data->{category} eq "ITEMLOST" ) {
271             $count++;
272             if ( $itemlost eq $data->{'authorised_value'} ) {
273                 $data->{'selected'} = 1;
274             }
275             $results[$count] = $data;
276
277             #warn "data: $data";
278         }
279     }
280     $sth->finish;
281     return ( $count, @results );
282 }
283
284 =head2 GetAuthItembinding
285
286 grab itemlost authorized values
287
288 =cut
289
290 sub GetAuthItembinding {
291     my $itembinding = shift;
292     my $count       = 0;
293     my @results;
294     my $dbh = C4::Context->dbh;
295     my $sth =
296       $dbh->prepare(
297         "SELECT * FROM authorised_values ORDER BY authorised_value");
298     $sth->execute;
299     while ( my $data = $sth->fetchrow_hashref ) {
300         if ( $data->{category} eq "BINDING" ) {
301             $count++;
302             if ( $itembinding eq $data->{'authorised_value'} ) {
303                 $data->{'selected'} = 1;
304             }
305             $results[$count] = $data;
306
307             #warn "data: $data";
308         }
309     }
310     $sth->finish;
311     return ( $count, @results );
312 }
313
314 =head2 getauthtypes
315
316   $authtypes = &getauthtypes();
317
318 Returns information about existing authtypes.
319
320 build a HTML select with the following code :
321
322 =head3 in PERL SCRIPT
323
324 my $authtypes = getauthtypes;
325 my @authtypesloop;
326 foreach my $thisauthtype (keys %$authtypes) {
327     my $selected = 1 if $thisauthtype eq $authtype;
328     my %row =(value => $thisauthtype,
329                 selected => $selected,
330                 authtypetext => $authtypes->{$thisauthtype}->{'authtypetext'},
331             );
332     push @authtypesloop, \%row;
333 }
334 $template->param(itemtypeloop => \@itemtypesloop);
335
336 =head3 in TEMPLATE
337
338 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
339     <select name="authtype">
340     <!-- TMPL_LOOP name="authtypeloop" -->
341         <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="authtypetext" --></option>
342     <!-- /TMPL_LOOP -->
343     </select>
344     <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
345     <input type="submit" value="OK" class="button">
346 </form>
347
348
349 =cut
350
351 sub getauthtypes {
352
353     # returns a reference to a hash of references to authtypes...
354     my %authtypes;
355     my $dbh = C4::Context->dbh;
356     my $sth = $dbh->prepare("select * from auth_types order by authtypetext");
357     $sth->execute;
358     while ( my $IT = $sth->fetchrow_hashref ) {
359         $authtypes{ $IT->{'authtypecode'} } = $IT;
360     }
361     return ( \%authtypes );
362 }
363
364 sub getauthtype {
365     my ($authtypecode) = @_;
366
367     # returns a reference to a hash of references to authtypes...
368     my %authtypes;
369     my $dbh = C4::Context->dbh;
370     my $sth = $dbh->prepare("select * from auth_types where authtypecode=?");
371     $sth->execute($authtypecode);
372     my $res = $sth->fetchrow_hashref;
373     return $res;
374 }
375
376 =head2 getframework
377
378   $frameworks = &getframework();
379
380 Returns information about existing frameworks
381
382 build a HTML select with the following code :
383
384 =head3 in PERL SCRIPT
385
386 my $frameworks = frameworks();
387 my @frameworkloop;
388 foreach my $thisframework (keys %$frameworks) {
389     my $selected = 1 if $thisframework eq $frameworkcode;
390     my %row =(value => $thisframework,
391                 selected => $selected,
392                 description => $frameworks->{$thisframework}->{'frameworktext'},
393             );
394     push @frameworksloop, \%row;
395 }
396 $template->param(frameworkloop => \@frameworksloop);
397
398 =head3 in TEMPLATE
399
400 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
401     <select name="frameworkcode">
402         <option value="">Default</option>
403     <!-- TMPL_LOOP name="frameworkloop" -->
404         <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="frameworktext" --></option>
405     <!-- /TMPL_LOOP -->
406     </select>
407     <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
408     <input type="submit" value="OK" class="button">
409 </form>
410
411
412 =cut
413
414 sub getframeworks {
415
416     # returns a reference to a hash of references to branches...
417     my %itemtypes;
418     my $dbh = C4::Context->dbh;
419     my $sth = $dbh->prepare("select * from biblio_framework");
420     $sth->execute;
421     while ( my $IT = $sth->fetchrow_hashref ) {
422         $itemtypes{ $IT->{'frameworkcode'} } = $IT;
423     }
424     return ( \%itemtypes );
425 }
426
427 =head2 getframeworkinfo
428
429   $frameworkinfo = &getframeworkinfo($frameworkcode);
430
431 Returns information about an frameworkcode.
432
433 =cut
434
435 sub getframeworkinfo {
436     my ($frameworkcode) = @_;
437     my $dbh             = C4::Context->dbh;
438     my $sth             =
439       $dbh->prepare("select * from biblio_framework where frameworkcode=?");
440     $sth->execute($frameworkcode);
441     my $res = $sth->fetchrow_hashref;
442     return $res;
443 }
444
445 =head2 getitemtypeinfo
446
447   $itemtype = &getitemtype($itemtype);
448
449 Returns information about an itemtype.
450
451 =cut
452
453 sub getitemtypeinfo {
454     my ($itemtype) = @_;
455     my $dbh        = C4::Context->dbh;
456     my $sth        = $dbh->prepare("select * from itemtypes where itemtype=?");
457     $sth->execute($itemtype);
458     my $res = $sth->fetchrow_hashref;
459
460     $res->{imageurl} = getitemtypeimagesrcfromurl( $res->{imageurl} );
461
462     return $res;
463 }
464
465 sub getitemtypeimagesrcfromurl {
466     my ($imageurl) = @_;
467
468     if ( defined $imageurl and $imageurl !~ m/^http/ ) {
469         $imageurl = getitemtypeimagesrc() . '/' . $imageurl;
470     }
471
472     return $imageurl;
473 }
474
475 sub getitemtypeimagedir {
476     return C4::Context->opachtdocs . '/'
477       . C4::Context->preference('template')
478       . '/itemtypeimg';
479 }
480
481 sub getitemtypeimagesrc {
482     return '/opac-tmpl' . '/'
483       . C4::Context->preference('template')
484       . '/itemtypeimg';
485 }
486
487 =head2 GetPrinters
488
489   $printers = &GetPrinters();
490   @queues = keys %$printers;
491
492 Returns information about existing printer queues.
493
494 C<$printers> is a reference-to-hash whose keys are the print queues
495 defined in the printers table of the Koha database. The values are
496 references-to-hash, whose keys are the fields in the printers table.
497
498 =cut
499
500 sub GetPrinters {
501     my %printers;
502     my $dbh = C4::Context->dbh;
503     my $sth = $dbh->prepare("select * from printers");
504     $sth->execute;
505     while ( my $printer = $sth->fetchrow_hashref ) {
506         $printers{ $printer->{'printqueue'} } = $printer;
507     }
508     return ( \%printers );
509 }
510
511 =head2 GetPrinter
512
513 $printer = GetPrinter( $query, $printers );
514
515 =cut
516
517 sub GetPrinter ($$) {
518     my ( $query, $printers ) = @_;    # get printer for this query from printers
519     my $printer = $query->param('printer');
520     my %cookie = $query->cookie('userenv');
521     ($printer) || ( $printer = $cookie{'printer'} ) || ( $printer = '' );
522     ( $printers->{$printer} ) || ( $printer = ( keys %$printers )[0] );
523     return $printer;
524 }
525
526 =item getnbpages
527
528 Returns the number of pages to display in a pagination bar, given the number
529 of items and the number of items per page.
530
531 =cut
532
533 sub getnbpages {
534     my ( $nb_items, $nb_items_per_page ) = @_;
535
536     return int( ( $nb_items - 1 ) / $nb_items_per_page ) + 1;
537 }
538
539 =item getallthemes
540
541   (@themes) = &getallthemes('opac');
542   (@themes) = &getallthemes('intranet');
543
544 Returns an array of all available themes.
545
546 =cut
547
548 sub getallthemes {
549     my $type = shift;
550     my $htdocs;
551     my @themes;
552     if ( $type eq 'intranet' ) {
553         $htdocs = C4::Context->config('intrahtdocs');
554     }
555     else {
556         $htdocs = C4::Context->config('opachtdocs');
557     }
558     opendir D, "$htdocs";
559     my @dirlist = readdir D;
560     foreach my $directory (@dirlist) {
561         -d "$htdocs/$directory/en" and push @themes, $directory;
562     }
563     return @themes;
564 }
565
566 sub getFacets {
567     my $facets;
568     if ( C4::Context->preference("marcflavour") eq "UNIMARC" ) {
569         $facets = [
570             {
571                 link_value  => 'su-to',
572                 label_value => 'Topics',
573                 tags        =>
574                   [ '600', '601', '602', '603', '604', '605', '606', '610' ],
575                 subfield => 'a',
576             },
577             {
578                 link_value  => 'su-geo',
579                 label_value => 'Places',
580                 tags        => ['651'],
581                 subfield    => 'a',
582             },
583             {
584                 link_value  => 'su-ut',
585                 label_value => 'Titles',
586                 tags        => [ '500', '501', '502', '503', '504', ],
587                 subfield    => 'a',
588             },
589             {
590                 link_value  => 'au',
591                 label_value => 'Authors',
592                 tags        => [ '700', '701', '702', ],
593                 subfield    => 'a',
594             },
595             {
596                 link_value  => 'se',
597                 label_value => 'Series',
598                 tags        => ['225'],
599                 subfield    => 'a',
600             },
601             {
602                 link_value  => 'branch',
603                 label_value => 'Branches',
604                 tags        => [ '995', ],
605                 subfield    => 'b',
606                 expanded    => '1',
607             },
608         ];
609     }
610     else {
611         $facets = [
612             {
613                 link_value  => 'su-to',
614                 label_value => 'Topics',
615                 tags        => ['650'],
616                 subfield    => 'a',
617             },
618
619             #        {
620             #        link_value => 'su-na',
621             #        label_value => 'People and Organizations',
622             #        tags => ['600', '610', '611'],
623             #        subfield => 'a',
624             #        },
625             {
626                 link_value  => 'su-geo',
627                 label_value => 'Places',
628                 tags        => ['651'],
629                 subfield    => 'a',
630             },
631             {
632                 link_value  => 'su-ut',
633                 label_value => 'Titles',
634                 tags        => ['630'],
635                 subfield    => 'a',
636             },
637             {
638                 link_value  => 'au',
639                 label_value => 'Authors',
640                 tags        => [ '100', '110', '700', ],
641                 subfield    => 'a',
642             },
643             {
644                 link_value  => 'se',
645                 label_value => 'Series',
646                 tags        => [ '440', '490', ],
647                 subfield    => 'a',
648             },
649             {
650                 link_value  => 'branch',
651                 label_value => 'Branches',
652                 tags        => [ '952', ],
653                 subfield    => 'b',
654                 expanded    => '1',
655             },
656         ];
657     }
658     return $facets;
659 }
660
661 =head2 get_infos_of
662
663 Return a href where a key is associated to a href. You give a query, the
664 name of the key among the fields returned by the query. If you also give as
665 third argument the name of the value, the function returns a href of scalar.
666
667   my $query = '
668 SELECT itemnumber,
669        notforloan,
670        barcode
671   FROM items
672 ';
673
674   # generic href of any information on the item, href of href.
675   my $iteminfos_of = get_infos_of($query, 'itemnumber');
676   print $iteminfos_of->{$itemnumber}{barcode};
677
678   # specific information, href of scalar
679   my $barcode_of_item = get_infos_of($query, 'itemnumber', 'barcode');
680   print $barcode_of_item->{$itemnumber};
681
682 =cut
683
684 sub get_infos_of {
685     my ( $query, $key_name, $value_name ) = @_;
686
687     my $dbh = C4::Context->dbh;
688
689     my $sth = $dbh->prepare($query);
690     $sth->execute();
691
692     my %infos_of;
693     while ( my $row = $sth->fetchrow_hashref ) {
694         if ( defined $value_name ) {
695             $infos_of{ $row->{$key_name} } = $row->{$value_name};
696         }
697         else {
698             $infos_of{ $row->{$key_name} } = $row;
699         }
700     }
701     $sth->finish;
702
703     return \%infos_of;
704 }
705
706 =head2 get_notforloan_label_of
707
708   my $notforloan_label_of = get_notforloan_label_of();
709
710 Each authorised value of notforloan (information available in items and
711 itemtypes) is link to a single label.
712
713 Returns a href where keys are authorised values and values are corresponding
714 labels.
715
716   foreach my $authorised_value (keys %{$notforloan_label_of}) {
717     printf(
718         "authorised_value: %s => %s\n",
719         $authorised_value,
720         $notforloan_label_of->{$authorised_value}
721     );
722   }
723
724 =cut
725
726 sub get_notforloan_label_of {
727     my $dbh = C4::Context->dbh;
728
729     my $query = '
730 SELECT authorised_value
731   FROM marc_subfield_structure
732   WHERE kohafield = \'items.notforloan\'
733   LIMIT 0, 1
734 ';
735     my $sth = $dbh->prepare($query);
736     $sth->execute();
737     my ($statuscode) = $sth->fetchrow_array();
738
739     $query = '
740 SELECT lib,
741        authorised_value
742   FROM authorised_values
743   WHERE category = ?
744 ';
745     $sth = $dbh->prepare($query);
746     $sth->execute($statuscode);
747     my %notforloan_label_of;
748     while ( my $row = $sth->fetchrow_hashref ) {
749         $notforloan_label_of{ $row->{authorised_value} } = $row->{lib};
750     }
751     $sth->finish;
752
753     return \%notforloan_label_of;
754 }
755
756 sub displaySortby {
757     my ($sort_by) = @_;
758     $sort_by =~ s/</\&lt;/;
759     $sort_by =~ s/>/\&gt;/;
760     my $sort_by_loop = [
761         { value => "1=9523 &gt;i", label => "Popularity (Most to Least)" },
762         { value => "1=9523 &lt;i", label => "Popularity (Least to Most)" },
763         { value => "1=1003 &lt;i", label => "Author (A-Z)" },
764         { value => "1=1003 &gt;i", label => "Author (Z-A)" },
765         {
766             value => "1=20 &lt;i",
767             label => "Call Number (Non-fiction 0-9 to Fiction A-Z)"
768         },
769         {
770             value => "1=20 &gt;i",
771             label => "Call Number (Fiction Z-A to Non-fiction 9-0)"
772         },
773         { value => "1=31 &gt;i", label => "Dates" },
774         {
775             value => "1=31 &gt;i",
776             label =>
777               "&nbsp;&nbsp;&nbsp;Publication/Copyright Date: Newest to Oldest"
778         },
779         {
780             value => "1=31 &lt;i",
781             label =>
782               "&nbsp;&nbsp;&nbsp;Publication/Copyright Date: Oldest to Newest"
783         },
784         {
785             value => "1=32 &gt;i",
786             label => "&nbsp;&nbsp;&nbsp;Acquisition Date: Newest to Oldest"
787         },
788         {
789             value => "1=32 &lt;i",
790             label => "&nbsp;&nbsp;&nbsp;Acquisition Date: Oldest to Newest"
791         },
792         { value => "1=36 &lt;i", label => "Title (A-Z)" },
793         { value => "1=36 &gt;i", label => "Title (Z-A)" },
794     ];
795     for my $hash (@$sort_by_loop) {
796
797         #warn "sort by: $sort_by ... hash:".$hash->{value};
798         if ($sort_by && $hash->{value} eq $sort_by ) {
799             $hash->{selected} = "selected";
800         }
801     }
802     return $sort_by_loop;
803
804 }
805
806 sub displayIndexes {
807     my $indexes = [
808         { value => '',   label => 'Keyword' },
809         { value => 'au', label => 'Author' },
810         {
811             value => 'au,phr',
812             label => '&nbsp;&nbsp;&nbsp;&nbsp; Author Phrase'
813         },
814         { value => 'cpn', label => '&nbsp;&nbsp;&nbsp;&nbsp; Corporate Name' },
815         { value => 'cfn', label => '&nbsp;&nbsp;&nbsp;&nbsp; Conference Name' },
816         {
817             value => 'cpn,phr',
818             label => '&nbsp;&nbsp;&nbsp;&nbsp; Corporate Name Phrase'
819         },
820         {
821             value => 'cfn,phr',
822             label => '&nbsp;&nbsp;&nbsp;&nbsp; Conference Name Phrase'
823         },
824         { value => 'pn', label => '&nbsp;&nbsp;&nbsp;&nbsp; Personal Name' },
825         {
826             value => 'pn,phr',
827             label => '&nbsp;&nbsp;&nbsp;&nbsp; Personal Name Phrase'
828         },
829         { value => 'ln', label => 'Language' },
830
831         #    { value => 'mt', label => 'Material Type' },
832         #    { value => 'mt,phr', label => 'Material Type Phrase' },
833         #    { value => 'mc', label => 'Musical Composition' },
834         #    { value => 'mc,phr', label => 'Musical Composition Phrase' },
835
836         { value => 'nt',  label => 'Notes/Comments' },
837         { value => 'pb',  label => 'Publisher' },
838         { value => 'pl',  label => 'Publisher Location' },
839         { value => 'sn',  label => 'Standard Number' },
840         { value => 'nb',  label => '&nbsp;&nbsp;&nbsp;&nbsp; ISBN' },
841         { value => 'ns',  label => '&nbsp;&nbsp;&nbsp;&nbsp; ISSN' },
842         { value => 'lcn', label => '&nbsp;&nbsp;&nbsp;&nbsp; Call Number' },
843         { value => 'su',  label => 'Subject' },
844         {
845             value => 'su,phr',
846             label => '&nbsp;&nbsp;&nbsp;&nbsp; Subject Phrase'
847         },
848
849 #    { value => 'de', label => '&nbsp;&nbsp;&nbsp;&nbsp; Descriptor' },
850 #    { value => 'ge', label => '&nbsp;&nbsp;&nbsp;&nbsp; Genre/Form' },
851 #    { value => 'gc', label => '&nbsp;&nbsp;&nbsp;&nbsp; Geographic Coverage' },
852
853 #     { value => 'nc', label => '&nbsp;&nbsp;&nbsp;&nbsp; Named Corporation and Conference' },
854 #     { value => 'na', label => '&nbsp;&nbsp;&nbsp;&nbsp; Named Person' },
855
856         { value => 'ti',     label => 'Title' },
857         { value => 'ti,phr', label => '&nbsp;&nbsp;&nbsp;&nbsp; Title Phrase' },
858         { value => 'se',     label => '&nbsp;&nbsp;&nbsp;&nbsp; Series Title' },
859     ];
860     return $indexes;
861 }
862
863 sub displaySubtypesLimit {
864     my $outer_subtype_limits_loop = [
865
866         {    # in MARC21, aud codes are stored in 008/22 (Target audience)
867             name                      => "limit",
868             inner_subtype_limits_loop => [
869                 {
870                     value    => '',
871                     label    => 'Any Audience',
872                     selected => "selected"
873                 },
874                 { value => 'aud:a', label => 'Easy', },
875                 { value => 'aud:c', label => 'Juvenile', },
876                 { value => 'aud:d', label => 'Young Adult', },
877                 { value => 'aud:e', label => 'Adult', },
878
879             ],
880         },
881         {    # in MARC21, fic is in 008/33, bio in 008/34, mus in LDR/06
882             name                      => "limit",
883             inner_subtype_limits_loop => [
884                 { value => '', label => 'Any Content', selected => "selected" },
885                 { value => 'fic:1', label => 'Fiction', },
886                 { value => 'fic:0', label => 'Non Fiction', },
887                 { value => 'bio:b', label => 'Biography', },
888                 { value => 'mus:j', label => 'Musical recording', },
889                 { value => 'mus:i', label => 'Non-musical recording', },
890
891             ],
892         },
893         {    # MARC21, these are codes stored in 007/00-01
894             name                      => "limit",
895             inner_subtype_limits_loop => [
896                 { value => '', label => 'Any Format', selected => "selected" },
897                 { value => 'l-format:ta', label => 'Regular print', },
898                 { value => 'l-format:tb', label => 'Large print', },
899                 { value => 'l-format:fk', label => 'Braille', },
900                 { value => '',            label => '-----------', },
901                 { value => 'l-format:sd', label => 'CD audio', },
902                 { value => 'l-format:ss', label => 'Cassette recording', },
903                 {
904                     value => 'l-format:vf',
905                     label => 'VHS tape / Videocassette',
906                 },
907                 { value => 'l-format:vd', label => 'DVD video / Videodisc', },
908                 { value => 'l-format:co', label => 'CD Software', },
909                 { value => 'l-format:cr', label => 'Website', },
910
911             ],
912         },
913         {    # in MARC21, these are codes in 008/24-28
914             name                      => "limit",
915             inner_subtype_limits_loop => [
916                 { value => '',        label => 'Additional Content Types', },
917                 { value => 'ctype:a', label => 'Abstracts/summaries', },
918                 { value => 'ctype:b', label => 'Bibliographies', },
919                 { value => 'ctype:c', label => 'Catalogs', },
920                 { value => 'ctype:d', label => 'Dictionaries', },
921                 { value => 'ctype:e', label => 'Encyclopedias ', },
922                 { value => 'ctype:f', label => 'Handbooks', },
923                 { value => 'ctype:g', label => 'Legal articles', },
924                 { value => 'ctype:i', label => 'Indexes', },
925                 { value => 'ctype:j', label => 'Patent document', },
926                 { value => 'ctype:k', label => 'Discographies', },
927                 { value => 'ctype:l', label => 'Legislation', },
928                 { value => 'ctype:m', label => 'Theses', },
929                 { value => 'ctype:n', label => 'Surveys', },
930                 { value => 'ctype:o', label => 'Reviews', },
931                 { value => 'ctype:p', label => 'Programmed texts', },
932                 { value => 'ctype:q', label => 'Filmographies', },
933                 { value => 'ctype:r', label => 'Directories', },
934                 { value => 'ctype:s', label => 'Statistics', },
935                 { value => 'ctype:t', label => 'Technical reports', },
936                 { value => 'ctype:v', label => 'Legal cases and case notes', },
937                 { value => 'ctype:w', label => 'Law reports and digests', },
938                 { value => 'ctype:z', label => 'Treaties ', },
939             ],
940         },
941     ];
942     return $outer_subtype_limits_loop;
943 }
944
945 sub displayLimitTypes {
946     my $outer_limit_types_loop = [
947
948         {
949             inner_limit_types_loop => [
950                 {
951                     label => "Books",
952                     id    => "mc-books",
953                     name  => "limit",
954                     value => "(mc-collection:AF or mc-collection:MYS or mc-collection:SCI or mc-collection:NF or mc-collection:YA or mc-collection:BIO or mc-collection:LP or mc-collection:LPNF)",
955                     icon  => "search-books.gif",
956                     title =>
957 "Books, Pamphlets, Technical reports, Manuscripts, Legal papers, Theses and dissertations",
958                 },
959
960                 {
961                     label => "Movies",
962                     id    => "mc-movies",
963                     name  => "limit",
964                     value => "(mc-collection:DVD or mc-collection:AV or mc-collection:AVJ or mc-collection:AVJN or mc-collection:AVJNF or mc-collection:AVNF)",
965                     icon  => "search-movies.gif",
966                     title =>
967 "Motion pictures, Videorecordings, Filmstrips, Slides, Transparencies, Photos, Cards, Charts, Drawings",
968                 },
969
970                 {
971                                         label => "Music",
972                                 id => "mc-music",
973                     name  => "limit",
974                     value => "(mc-collection:CDM)",
975                     icon  => "search-music.gif",
976                     title => "Spoken, Books on CD and Cassette",
977                 },
978             ],
979         },
980         {
981             inner_limit_types_loop => [
982                 {
983                     label => "Audio Books",
984                                         id => "mc-audio-books",
985                     name  => "limit",
986                     value => "(mc-collection:AB or mc-collection:AC or mc-collection:JAC or mc-collection:YAC)",
987                     icon  => "search-audio-books.gif",
988                     title => "Spoken, Books on CD and Cassette",
989                 },
990
991                 {
992                     label => "Local History Materials",
993                                 id => "mc-local-history",
994                     name  => "limit",
995                     value => "mc-collection:LH",
996                     icon  => "Local history.gif",
997                     title => "Local History Materials",
998                 },
999
1000     {label => "Large Print",
1001     id => "mc-large-print",
1002                     name  => "limit",
1003     value => "(mc-collection:LP or mc-collection:LPNF)",
1004     icon => "search-large-print.gif ",
1005     title => "Large Print",},
1006             ],
1007         },
1008 { inner_limit_types_loop => [
1009     {label => "Kids",
1010     id => "mc-kids",
1011                     name  => "limit",
1012     value => "(mc-collection:EASY or mc-collection:JNF or mc-collection:JF or mc-collection:JREF or mc-collection:JB)",
1013     icon => "search-kids.gif",
1014     title => "Music",},
1015
1016     {label => "Software/Internet",
1017     id => "mc-sofware-web",
1018                     name  => "limit",
1019     value => "(mc-collection:CDR)",
1020     icon => "search-software-web.gif",
1021     title => "Kits",},
1022
1023     {label => "Reference",
1024     id => "mc-reference",
1025                     name  => "limit",
1026                     value => "mc-collection:REF",
1027     icon => "search-reference.gif",
1028     title => "Reference",},
1029
1030             ],
1031         },
1032
1033     ];
1034     return $outer_limit_types_loop;
1035 }
1036
1037 sub displayServers {
1038     my ( $position, $type ) = @_;
1039     my $dbh    = C4::Context->dbh;
1040     my $strsth = "SELECT * FROM z3950servers where 1";
1041     $strsth .= " AND position=\"$position\"" if ($position);
1042     $strsth .= " AND type=\"$type\""         if ($type);
1043     my $rq = $dbh->prepare($strsth);
1044     $rq->execute;
1045     my @primaryserverloop;
1046
1047     while ( my $data = $rq->fetchrow_hashref ) {
1048         my %cell;
1049         $cell{label} = $data->{'description'};
1050         $cell{id}    = $data->{'name'};
1051         $cell{value} =
1052             $data->{host}
1053           . ( $data->{port} ? ":" . $data->{port} : "" ) . "/"
1054           . $data->{database}
1055           if ( $data->{host} );
1056         $cell{checked} = $data->{checked};
1057         push @primaryserverloop,
1058           {
1059             label => $data->{description},
1060             id    => $data->{name},
1061             name  => "server",
1062             value => $data->{host} . ":"
1063               . $data->{port} . "/"
1064               . $data->{database},
1065             checked    => "checked",
1066             icon       => $data->{icon},
1067             zed        => $data->{type} eq 'zed',
1068             opensearch => $data->{type} eq 'opensearch'
1069           };
1070     }
1071     return \@primaryserverloop;
1072 }
1073
1074 sub displaySecondaryServers {
1075
1076 #       my $secondary_servers_loop = [
1077 #               { inner_sup_servers_loop => [
1078 #               {label => "Google", id=>"GOOG", value=>"google",icon => "google.ico",opensearch => "1"},
1079 #               {label => "Yahoo", id=>"YAH", value=>"yahoo", icon =>"yahoo.ico", zed => "1"},
1080 #               {label => "Worldcat", id=>"WCT", value=>"worldcat", icon => "worldcat.gif", zed => "1"},
1081 #               {label => "Library of Congress", id=>"LOC", name=> "server", value=>"z3950.loc.gov:7090/Voyager", icon =>"loc.ico", zed => "1"},
1082 #       ],
1083 #       },
1084 #       ];
1085     return;    #$secondary_servers_loop;
1086 }
1087
1088 =head2 GetAuthorisedValues
1089
1090 $authvalues = GetAuthorisedValues($category);
1091
1092 this function get all authorised values from 'authosied_value' table into a reference to array which
1093 each value containt an hashref.
1094
1095 Set C<$category> on input args if you want to limits your query to this one. This params is not mandatory.
1096
1097 =cut
1098
1099 sub GetAuthorisedValues {
1100     my $category = shift;
1101     my $dbh      = C4::Context->dbh;
1102     my $query    = "SELECT * FROM authorised_values";
1103     $query .= " WHERE category = '" . $category . "'" if $category;
1104
1105     my $sth = $dbh->prepare($query);
1106     $sth->execute;
1107     my $data = $sth->fetchall_arrayref({});
1108     return $data;
1109 }
1110
1111 =item fixEncoding
1112
1113   $marcrecord = &fixEncoding($marcblob);
1114
1115 Returns a well encoded marcrecord.
1116
1117 =cut
1118 sub FixEncoding {
1119   my $marc=shift;
1120   my $record = MARC::Record->new_from_usmarc($marc);
1121   if (C4::Context->preference("MARCFLAVOUR") eq "UNIMARC"){
1122     use Encode::Guess;
1123     my $targetcharset="utf8" if (C4::Context->preference("TemplateEncoding") eq "utf-8");
1124     $targetcharset="latin1" if (C4::Context->preference("TemplateEncoding") eq "iso-8859-1");
1125     my $decoder = guess_encoding($marc, qw/utf8 latin1/);
1126 #     die $decoder unless ref($decoder);
1127     if (ref($decoder)) {
1128         my $newRecord=MARC::Record->new();
1129         foreach my $field ($record->fields()){
1130         if ($field->tag()<'010'){
1131             $newRecord->insert_grouped_field($field);
1132         } else {
1133             my $newField;
1134             my $createdfield=0;
1135             foreach my $subfield ($field->subfields()){
1136             if ($createdfield){
1137                 if (($newField->tag eq '100')) {
1138                 substr($subfield->[1],26,2,"0103") if ($targetcharset eq "latin1");
1139                 substr($subfield->[1],26,4,"5050") if ($targetcharset eq "utf8");
1140                 }
1141                 map {C4::Biblio::char_decode($_,"UNIMARC")} @$subfield;
1142                 $newField->add_subfields($subfield->[0]=>$subfield->[1]);
1143             } else {
1144                 map {C4::Biblio::char_decode($_,"UNIMARC")} @$subfield;
1145                 $newField=MARC::Field->new($field->tag(),$field->indicator(1),$field->indicator(2),$subfield->[0]=>$subfield->[1]);
1146                 $createdfield=1;
1147             }
1148             }
1149             $newRecord->insert_grouped_field($newField);
1150         }
1151         }
1152     #     warn $newRecord->as_formatted(); 
1153         return $newRecord;
1154     } else {
1155         return $record;
1156     }
1157   } else {
1158     return $record;
1159   }
1160 }
1161
1162 =head2 GetKohaAuthorisedValues
1163         
1164         Takes $dbh , $kohafield as parameters.
1165         returns hashref of authvalCode => liblibrarian
1166         or undef if no authvals defined for kohafield.
1167
1168 =cut
1169
1170 sub GetKohaAuthorisedValues {
1171   my ($kohafield) = @_;
1172   my %values;
1173   my $dbh = C4::Context->dbh;
1174   my $sthnflstatus = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield=?');
1175   $sthnflstatus->execute($kohafield);
1176   my $authorised_valuecode = $sthnflstatus->fetchrow;
1177   if ($authorised_valuecode) {  
1178     $sthnflstatus = $dbh->prepare("select authorised_value, lib from authorised_values where category=? ");
1179     $sthnflstatus->execute($authorised_valuecode);
1180     while ( my ($val, $lib) = $sthnflstatus->fetchrow_array ) { 
1181       $values{$val}= $lib;
1182     }
1183   }
1184   return \%values;
1185 }
1186
1187
1188 1;
1189
1190 __END__
1191
1192 =back
1193
1194 =head1 AUTHOR
1195
1196 Koha Team
1197
1198 =cut