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