3 # Copyright 2000-2002 Katipo Communications
5 # This file is part of Koha.
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
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.
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
25 our ($VERSION,@ISA,@EXPORT);
31 C4::Koha - Perl Module containing convenience functions for Koha scripts
40 Koha.pm provides many functions for Koha scripts.
52 &subfield_is_koha_internal_p
53 &GetPrinters &GetPrinter
54 &GetItemTypes &getitemtypeinfo
59 &getframeworks &getframeworkinfo
60 &getauthtypes &getauthtype
65 &getitemtypeimagesrcfromurl
67 &get_notforloan_label_of
72 &GetKohaAuthorisedValues
73 &GetManagedTagSubfields
82 $slash_date = &slashifyDate($dash_date);
84 Takes a string of the form "DD-MM-YYYY" (or anything separated by
85 dashes), converts it to the form "YYYY/MM/DD", and returns the result.
91 # accepts a date of the form xx-xx-xx[xx] and returns it in the
93 my @dateOut = split( '-', shift );
94 return ("$dateOut[2]/$dateOut[1]/$dateOut[0]");
100 my $string = DisplayISBN( $isbn );
106 if (length ($isbn)<13){
108 if ( substr( $isbn, 0, 1 ) <= 7 ) {
109 $seg1 = substr( $isbn, 0, 1 );
111 elsif ( substr( $isbn, 0, 2 ) <= 94 ) {
112 $seg1 = substr( $isbn, 0, 2 );
114 elsif ( substr( $isbn, 0, 3 ) <= 995 ) {
115 $seg1 = substr( $isbn, 0, 3 );
117 elsif ( substr( $isbn, 0, 4 ) <= 9989 ) {
118 $seg1 = substr( $isbn, 0, 4 );
121 $seg1 = substr( $isbn, 0, 5 );
123 my $x = substr( $isbn, length($seg1) );
125 if ( substr( $x, 0, 2 ) <= 19 ) {
127 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
128 $seg2 = substr( $x, 0, 2 );
130 elsif ( substr( $x, 0, 3 ) <= 699 ) {
131 $seg2 = substr( $x, 0, 3 );
133 elsif ( substr( $x, 0, 4 ) <= 8399 ) {
134 $seg2 = substr( $x, 0, 4 );
136 elsif ( substr( $x, 0, 5 ) <= 89999 ) {
137 $seg2 = substr( $x, 0, 5 );
139 elsif ( substr( $x, 0, 6 ) <= 9499999 ) {
140 $seg2 = substr( $x, 0, 6 );
143 $seg2 = substr( $x, 0, 7 );
145 my $seg3 = substr( $x, length($seg2) );
146 $seg3 = substr( $seg3, 0, length($seg3) - 1 );
147 my $seg4 = substr( $x, -1, 1 );
148 return "$seg1-$seg2-$seg3-$seg4";
151 $seg1 = substr( $isbn, 0, 3 );
153 if ( substr( $isbn, 3, 1 ) <= 7 ) {
154 $seg2 = substr( $isbn, 3, 1 );
156 elsif ( substr( $isbn, 3, 2 ) <= 94 ) {
157 $seg2 = substr( $isbn, 3, 2 );
159 elsif ( substr( $isbn, 3, 3 ) <= 995 ) {
160 $seg2 = substr( $isbn, 3, 3 );
162 elsif ( substr( $isbn, 3, 4 ) <= 9989 ) {
163 $seg2 = substr( $isbn, 3, 4 );
166 $seg2 = substr( $isbn, 3, 5 );
168 my $x = substr( $isbn, length($seg2) +3);
170 if ( substr( $x, 0, 2 ) <= 19 ) {
172 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
173 $seg3 = substr( $x, 0, 2 );
175 elsif ( substr( $x, 0, 3 ) <= 699 ) {
176 $seg3 = substr( $x, 0, 3 );
178 elsif ( substr( $x, 0, 4 ) <= 8399 ) {
179 $seg3 = substr( $x, 0, 4 );
181 elsif ( substr( $x, 0, 5 ) <= 89999 ) {
182 $seg3 = substr( $x, 0, 5 );
184 elsif ( substr( $x, 0, 6 ) <= 9499999 ) {
185 $seg3 = substr( $x, 0, 6 );
188 $seg3 = substr( $x, 0, 7 );
190 my $seg4 = substr( $x, length($seg3) );
191 $seg4 = substr( $seg4, 0, length($seg4) - 1 );
192 my $seg5 = substr( $x, -1, 1 );
193 return "$seg1-$seg2-$seg3-$seg4-$seg5";
197 # FIXME.. this should be moved to a MARC-specific module
198 sub subfield_is_koha_internal_p ($) {
201 # We could match on 'lib' and 'tab' (and 'mandatory', & more to come!)
202 # But real MARC subfields are always single-character
203 # so it really is safer just to check the length
205 return length $subfield != 1;
210 $itemtypes = &GetItemTypes();
212 Returns information about existing itemtypes.
214 build a HTML select with the following code :
216 =head3 in PERL SCRIPT
218 my $itemtypes = GetItemTypes;
220 foreach my $thisitemtype (sort keys %$itemtypes) {
221 my $selected = 1 if $thisitemtype eq $itemtype;
222 my %row =(value => $thisitemtype,
223 selected => $selected,
224 description => $itemtypes->{$thisitemtype}->{'description'},
226 push @itemtypesloop, \%row;
228 $template->param(itemtypeloop => \@itemtypesloop);
232 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
233 <select name="itemtype">
234 <option value="">Default</option>
235 <!-- TMPL_LOOP name="itemtypeloop" -->
236 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="description" --></option>
239 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
240 <input type="submit" value="OK" class="button">
247 # returns a reference to a hash of references to branches...
249 my $dbh = C4::Context->dbh;
254 my $sth = $dbh->prepare($query);
256 while ( my $IT = $sth->fetchrow_hashref ) {
257 $itemtypes{ $IT->{'itemtype'} } = $IT;
259 return ( \%itemtypes );
262 sub get_itemtypeinfos_of {
270 WHERE itemtype IN (' . join( ',', map( { "'" . $_ . "'" } @itemtypes ) ) . ')
273 return get_infos_of( $query, 'itemtype' );
276 # this is temporary until we separate collection codes and item types
280 my $dbh = C4::Context->dbh;
283 "SELECT * FROM authorised_values ORDER BY authorised_value");
285 while ( my $data = $sth->fetchrow_hashref ) {
286 if ( $data->{category} eq "CCODE" ) {
288 $results[$count] = $data;
294 return ( $count, @results );
299 grab itemlost authorized values
303 sub GetAuthItemlost {
304 my $itemlost = shift;
307 my $dbh = C4::Context->dbh;
310 "SELECT * FROM authorised_values ORDER BY authorised_value");
312 while ( my $data = $sth->fetchrow_hashref ) {
313 if ( $data->{category} eq "ITEMLOST" ) {
315 if ( $itemlost eq $data->{'authorised_value'} ) {
316 $data->{'selected'} = 1;
318 $results[$count] = $data;
324 return ( $count, @results );
329 $authtypes = &getauthtypes();
331 Returns information about existing authtypes.
333 build a HTML select with the following code :
335 =head3 in PERL SCRIPT
337 my $authtypes = getauthtypes;
339 foreach my $thisauthtype (keys %$authtypes) {
340 my $selected = 1 if $thisauthtype eq $authtype;
341 my %row =(value => $thisauthtype,
342 selected => $selected,
343 authtypetext => $authtypes->{$thisauthtype}->{'authtypetext'},
345 push @authtypesloop, \%row;
347 $template->param(itemtypeloop => \@itemtypesloop);
351 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
352 <select name="authtype">
353 <!-- TMPL_LOOP name="authtypeloop" -->
354 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="authtypetext" --></option>
357 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
358 <input type="submit" value="OK" class="button">
366 # returns a reference to a hash of references to authtypes...
368 my $dbh = C4::Context->dbh;
369 my $sth = $dbh->prepare("select * from auth_types order by authtypetext");
371 while ( my $IT = $sth->fetchrow_hashref ) {
372 $authtypes{ $IT->{'authtypecode'} } = $IT;
374 return ( \%authtypes );
378 my ($authtypecode) = @_;
380 # returns a reference to a hash of references to authtypes...
382 my $dbh = C4::Context->dbh;
383 my $sth = $dbh->prepare("select * from auth_types where authtypecode=?");
384 $sth->execute($authtypecode);
385 my $res = $sth->fetchrow_hashref;
391 $frameworks = &getframework();
393 Returns information about existing frameworks
395 build a HTML select with the following code :
397 =head3 in PERL SCRIPT
399 my $frameworks = frameworks();
401 foreach my $thisframework (keys %$frameworks) {
402 my $selected = 1 if $thisframework eq $frameworkcode;
403 my %row =(value => $thisframework,
404 selected => $selected,
405 description => $frameworks->{$thisframework}->{'frameworktext'},
407 push @frameworksloop, \%row;
409 $template->param(frameworkloop => \@frameworksloop);
413 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
414 <select name="frameworkcode">
415 <option value="">Default</option>
416 <!-- TMPL_LOOP name="frameworkloop" -->
417 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="frameworktext" --></option>
420 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
421 <input type="submit" value="OK" class="button">
429 # returns a reference to a hash of references to branches...
431 my $dbh = C4::Context->dbh;
432 my $sth = $dbh->prepare("select * from biblio_framework");
434 while ( my $IT = $sth->fetchrow_hashref ) {
435 $itemtypes{ $IT->{'frameworkcode'} } = $IT;
437 return ( \%itemtypes );
440 =head2 getframeworkinfo
442 $frameworkinfo = &getframeworkinfo($frameworkcode);
444 Returns information about an frameworkcode.
448 sub getframeworkinfo {
449 my ($frameworkcode) = @_;
450 my $dbh = C4::Context->dbh;
452 $dbh->prepare("select * from biblio_framework where frameworkcode=?");
453 $sth->execute($frameworkcode);
454 my $res = $sth->fetchrow_hashref;
458 =head2 getitemtypeinfo
460 $itemtype = &getitemtype($itemtype);
462 Returns information about an itemtype.
466 sub getitemtypeinfo {
468 my $dbh = C4::Context->dbh;
469 my $sth = $dbh->prepare("select * from itemtypes where itemtype=?");
470 $sth->execute($itemtype);
471 my $res = $sth->fetchrow_hashref;
473 $res->{imageurl} = getitemtypeimagesrcfromurl( $res->{imageurl} );
478 sub getitemtypeimagesrcfromurl {
481 if ( defined $imageurl and $imageurl !~ m/^http/ ) {
482 $imageurl = getitemtypeimagesrc() . '/' . $imageurl;
488 sub getitemtypeimagedir {
489 return C4::Context->opachtdocs . '/'
490 . C4::Context->preference('template')
494 sub getitemtypeimagesrc {
495 return '/opac-tmpl' . '/'
496 . C4::Context->preference('template')
502 $printers = &GetPrinters();
503 @queues = keys %$printers;
505 Returns information about existing printer queues.
507 C<$printers> is a reference-to-hash whose keys are the print queues
508 defined in the printers table of the Koha database. The values are
509 references-to-hash, whose keys are the fields in the printers table.
515 my $dbh = C4::Context->dbh;
516 my $sth = $dbh->prepare("select * from printers");
518 while ( my $printer = $sth->fetchrow_hashref ) {
519 $printers{ $printer->{'printqueue'} } = $printer;
521 return ( \%printers );
526 $printer = GetPrinter( $query, $printers );
530 sub GetPrinter ($$) {
531 my ( $query, $printers ) = @_; # get printer for this query from printers
532 my $printer = $query->param('printer');
533 my %cookie = $query->cookie('userenv');
534 ($printer) || ( $printer = $cookie{'printer'} ) || ( $printer = '' );
535 ( $printers->{$printer} ) || ( $printer = ( keys %$printers )[0] );
541 Returns the number of pages to display in a pagination bar, given the number
542 of items and the number of items per page.
547 my ( $nb_items, $nb_items_per_page ) = @_;
549 return int( ( $nb_items - 1 ) / $nb_items_per_page ) + 1;
554 (@themes) = &getallthemes('opac');
555 (@themes) = &getallthemes('intranet');
557 Returns an array of all available themes.
565 if ( $type eq 'intranet' ) {
566 $htdocs = C4::Context->config('intrahtdocs');
569 $htdocs = C4::Context->config('opachtdocs');
571 opendir D, "$htdocs";
572 my @dirlist = readdir D;
573 foreach my $directory (@dirlist) {
574 -d "$htdocs/$directory/en" and push @themes, $directory;
581 if ( C4::Context->preference("marcflavour") eq "UNIMARC" ) {
584 link_value => 'su-to',
585 label_value => 'Topics',
587 [ '600', '601', '602', '603', '604', '605', '606', '610' ],
591 link_value => 'su-geo',
592 label_value => 'Places',
597 link_value => 'su-ut',
598 label_value => 'Titles',
599 tags => [ '500', '501', '502', '503', '504', ],
604 label_value => 'Authors',
605 tags => [ '700', '701', '702', ],
610 label_value => 'Series',
615 link_value => 'branch',
616 label_value => 'Branches',
626 link_value => 'su-to',
627 label_value => 'Topics',
633 # link_value => 'su-na',
634 # label_value => 'People and Organizations',
635 # tags => ['600', '610', '611'],
639 link_value => 'su-geo',
640 label_value => 'Places',
645 link_value => 'su-ut',
646 label_value => 'Titles',
652 label_value => 'Authors',
653 tags => [ '100', '110', '700', ],
658 label_value => 'Series',
659 tags => [ '440', '490', ],
663 link_value => 'branch',
664 label_value => 'Branches',
676 Return a href where a key is associated to a href. You give a query, the
677 name of the key among the fields returned by the query. If you also give as
678 third argument the name of the value, the function returns a href of scalar.
687 # generic href of any information on the item, href of href.
688 my $iteminfos_of = get_infos_of($query, 'itemnumber');
689 print $iteminfos_of->{$itemnumber}{barcode};
691 # specific information, href of scalar
692 my $barcode_of_item = get_infos_of($query, 'itemnumber', 'barcode');
693 print $barcode_of_item->{$itemnumber};
698 my ( $query, $key_name, $value_name ) = @_;
700 my $dbh = C4::Context->dbh;
702 my $sth = $dbh->prepare($query);
706 while ( my $row = $sth->fetchrow_hashref ) {
707 if ( defined $value_name ) {
708 $infos_of{ $row->{$key_name} } = $row->{$value_name};
711 $infos_of{ $row->{$key_name} } = $row;
719 =head2 get_notforloan_label_of
721 my $notforloan_label_of = get_notforloan_label_of();
723 Each authorised value of notforloan (information available in items and
724 itemtypes) is link to a single label.
726 Returns a href where keys are authorised values and values are corresponding
729 foreach my $authorised_value (keys %{$notforloan_label_of}) {
731 "authorised_value: %s => %s\n",
733 $notforloan_label_of->{$authorised_value}
739 sub get_notforloan_label_of {
740 my $dbh = C4::Context->dbh;
743 SELECT authorised_value
744 FROM marc_subfield_structure
745 WHERE kohafield = \'items.notforloan\'
748 my $sth = $dbh->prepare($query);
750 my ($statuscode) = $sth->fetchrow_array();
755 FROM authorised_values
758 $sth = $dbh->prepare($query);
759 $sth->execute($statuscode);
760 my %notforloan_label_of;
761 while ( my $row = $sth->fetchrow_hashref ) {
762 $notforloan_label_of{ $row->{authorised_value} } = $row->{lib};
766 return \%notforloan_label_of;
770 my ( $position, $type ) = @_;
771 my $dbh = C4::Context->dbh;
772 my $strsth = "SELECT * FROM z3950servers where 1";
773 $strsth .= " AND position=\"$position\"" if ($position);
774 $strsth .= " AND type=\"$type\"" if ($type);
775 my $rq = $dbh->prepare($strsth);
777 my @primaryserverloop;
779 while ( my $data = $rq->fetchrow_hashref ) {
781 $cell{label} = $data->{'description'};
782 $cell{id} = $data->{'name'};
785 . ( $data->{port} ? ":" . $data->{port} : "" ) . "/"
787 if ( $data->{host} );
788 $cell{checked} = $data->{checked};
789 push @primaryserverloop,
791 label => $data->{description},
794 value => $data->{host} . ":"
795 . $data->{port} . "/"
797 checked => "checked",
798 icon => $data->{icon},
799 zed => $data->{type} eq 'zed',
800 opensearch => $data->{type} eq 'opensearch'
803 return \@primaryserverloop;
806 sub displaySecondaryServers {
808 # my $secondary_servers_loop = [
809 # { inner_sup_servers_loop => [
810 # {label => "Google", id=>"GOOG", value=>"google",icon => "google.ico",opensearch => "1"},
811 # {label => "Yahoo", id=>"YAH", value=>"yahoo", icon =>"yahoo.ico", zed => "1"},
812 # {label => "Worldcat", id=>"WCT", value=>"worldcat", icon => "worldcat.gif", zed => "1"},
813 # {label => "Library of Congress", id=>"LOC", name=> "server", value=>"z3950.loc.gov:7090/Voyager", icon =>"loc.ico", zed => "1"},
817 return; #$secondary_servers_loop;
820 =head2 GetAuthorisedValues
822 $authvalues = GetAuthorisedValues($category);
824 this function get all authorised values from 'authosied_value' table into a reference to array which
825 each value containt an hashref.
827 Set C<$category> on input args if you want to limits your query to this one. This params is not mandatory.
831 sub GetAuthorisedValues {
832 my $category = shift;
833 my $dbh = C4::Context->dbh;
834 my $query = "SELECT * FROM authorised_values";
835 $query .= " WHERE category = '" . $category . "'" if $category;
837 my $sth = $dbh->prepare($query);
839 my $data = $sth->fetchall_arrayref({});
845 $marcrecord = &fixEncoding($marcblob);
847 Returns a well encoded marcrecord.
852 my $record = MARC::Record->new_from_usmarc($marc);
853 if (C4::Context->preference("MARCFLAVOUR") eq "UNIMARC"){
855 my $targetcharset="utf8" if (C4::Context->preference("TemplateEncoding") eq "utf-8");
856 $targetcharset="latin1" if (C4::Context->preference("TemplateEncoding") eq "iso-8859-1");
857 my $decoder = guess_encoding($marc, qw/utf8 latin1/);
858 # die $decoder unless ref($decoder);
860 my $newRecord=MARC::Record->new();
861 foreach my $field ($record->fields()){
862 if ($field->tag()<'010'){
863 $newRecord->insert_grouped_field($field);
867 foreach my $subfield ($field->subfields()){
869 if (($newField->tag eq '100')) {
870 substr($subfield->[1],26,2,"0103") if ($targetcharset eq "latin1");
871 substr($subfield->[1],26,4,"5050") if ($targetcharset eq "utf8");
873 map {C4::Biblio::char_decode($_,"UNIMARC")} @$subfield;
874 $newField->add_subfields($subfield->[0]=>$subfield->[1]);
876 map {C4::Biblio::char_decode($_,"UNIMARC")} @$subfield;
877 $newField=MARC::Field->new($field->tag(),$field->indicator(1),$field->indicator(2),$subfield->[0]=>$subfield->[1]);
881 $newRecord->insert_grouped_field($newField);
884 # warn $newRecord->as_formatted();
894 =head2 GetKohaAuthorisedValues
896 Takes $dbh , $kohafield as parameters.
897 returns hashref of authvalCode => liblibrarian
898 or undef if no authvals defined for kohafield.
902 sub GetKohaAuthorisedValues {
903 my ($kohafield) = @_;
905 my $dbh = C4::Context->dbh;
906 my $sthnflstatus = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield=?');
907 $sthnflstatus->execute($kohafield);
908 my $authorised_valuecode = $sthnflstatus->fetchrow;
909 if ($authorised_valuecode) {
910 $sthnflstatus = $dbh->prepare("select authorised_value, lib from authorised_values where category=? ");
911 $sthnflstatus->execute($authorised_valuecode);
912 while ( my ($val, $lib) = $sthnflstatus->fetchrow_array ) {
919 =head2 GetManagedTagSubfields
923 $res = GetManagedTagSubfields();
925 Returns a reference to a big hash of hash, with the Marc structure fro the given frameworkcode
926 $forlibrarian :if set to 1, the MARC descriptions are the librarians ones, otherwise it's the public (OPAC) ones
927 $frameworkcode : the framework code to read
935 sub GetManagedTagSubfields{
936 my $dbh=C4::Context->dbh;
937 my $rq=$dbh->prepare(qq|
939 DISTINCT CONCAT( marc_subfield_structure.tagfield, tagsubfield ) AS tagsubfield,
940 marc_subfield_structure.liblibrarian as subfielddesc,
941 marc_tag_structure.liblibrarian as tagdesc
942 FROM marc_subfield_structure
943 LEFT JOIN marc_tag_structure
944 ON marc_tag_structure.tagfield = marc_subfield_structure.tagfield
945 AND marc_tag_structure.frameworkcode = marc_subfield_structure.frameworkcode
946 WHERE marc_subfield_structure.tab>=0
947 ORDER BY tagsubfield|);
949 my $data=$rq->fetchall_arrayref({});