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
17 # with Koha; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 use URI::Split qw(uri_split);
27 use vars qw($VERSION @ISA @EXPORT $DEBUG);
36 &subfield_is_koha_internal_p
37 &GetPrinters &GetPrinter
38 &GetItemTypes &getitemtypeinfo
40 &GetSupportName &GetSupportList
42 &getframeworks &getframeworkinfo
43 &getauthtypes &getauthtype
49 &get_notforloan_label_of
52 &getitemtypeimagelocation
54 &GetAuthorisedValueCategories
55 &GetKohaAuthorisedValues
56 &GetKohaAuthorisedValuesFromField
61 &GetNormalizedOCLCNumber
69 memoize('GetAuthorisedValues');
73 C4::Koha - Perl Module containing convenience functions for Koha scripts
82 Koha.pm provides many functions for Koha scripts.
90 $slash_date = &slashifyDate($dash_date);
92 Takes a string of the form "DD-MM-YYYY" (or anything separated by
93 dashes), converts it to the form "YYYY/MM/DD", and returns the result.
99 # accepts a date of the form xx-xx-xx[xx] and returns it in the
101 my @dateOut = split( '-', shift );
102 return ("$dateOut[2]/$dateOut[1]/$dateOut[0]");
108 my $string = DisplayISBN( $isbn );
114 if (length ($isbn)<13){
116 if ( substr( $isbn, 0, 1 ) <= 7 ) {
117 $seg1 = substr( $isbn, 0, 1 );
119 elsif ( substr( $isbn, 0, 2 ) <= 94 ) {
120 $seg1 = substr( $isbn, 0, 2 );
122 elsif ( substr( $isbn, 0, 3 ) <= 995 ) {
123 $seg1 = substr( $isbn, 0, 3 );
125 elsif ( substr( $isbn, 0, 4 ) <= 9989 ) {
126 $seg1 = substr( $isbn, 0, 4 );
129 $seg1 = substr( $isbn, 0, 5 );
131 my $x = substr( $isbn, length($seg1) );
133 if ( substr( $x, 0, 2 ) <= 19 ) {
135 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
136 $seg2 = substr( $x, 0, 2 );
138 elsif ( substr( $x, 0, 3 ) <= 699 ) {
139 $seg2 = substr( $x, 0, 3 );
141 elsif ( substr( $x, 0, 4 ) <= 8399 ) {
142 $seg2 = substr( $x, 0, 4 );
144 elsif ( substr( $x, 0, 5 ) <= 89999 ) {
145 $seg2 = substr( $x, 0, 5 );
147 elsif ( substr( $x, 0, 6 ) <= 9499999 ) {
148 $seg2 = substr( $x, 0, 6 );
151 $seg2 = substr( $x, 0, 7 );
153 my $seg3 = substr( $x, length($seg2) );
154 $seg3 = substr( $seg3, 0, length($seg3) - 1 );
155 my $seg4 = substr( $x, -1, 1 );
156 return "$seg1-$seg2-$seg3-$seg4";
159 $seg1 = substr( $isbn, 0, 3 );
161 if ( substr( $isbn, 3, 1 ) <= 7 ) {
162 $seg2 = substr( $isbn, 3, 1 );
164 elsif ( substr( $isbn, 3, 2 ) <= 94 ) {
165 $seg2 = substr( $isbn, 3, 2 );
167 elsif ( substr( $isbn, 3, 3 ) <= 995 ) {
168 $seg2 = substr( $isbn, 3, 3 );
170 elsif ( substr( $isbn, 3, 4 ) <= 9989 ) {
171 $seg2 = substr( $isbn, 3, 4 );
174 $seg2 = substr( $isbn, 3, 5 );
176 my $x = substr( $isbn, length($seg2) +3);
178 if ( substr( $x, 0, 2 ) <= 19 ) {
180 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
181 $seg3 = substr( $x, 0, 2 );
183 elsif ( substr( $x, 0, 3 ) <= 699 ) {
184 $seg3 = substr( $x, 0, 3 );
186 elsif ( substr( $x, 0, 4 ) <= 8399 ) {
187 $seg3 = substr( $x, 0, 4 );
189 elsif ( substr( $x, 0, 5 ) <= 89999 ) {
190 $seg3 = substr( $x, 0, 5 );
192 elsif ( substr( $x, 0, 6 ) <= 9499999 ) {
193 $seg3 = substr( $x, 0, 6 );
196 $seg3 = substr( $x, 0, 7 );
198 my $seg4 = substr( $x, length($seg3) );
199 $seg4 = substr( $seg4, 0, length($seg4) - 1 );
200 my $seg5 = substr( $x, -1, 1 );
201 return "$seg1-$seg2-$seg3-$seg4-$seg5";
205 # FIXME.. this should be moved to a MARC-specific module
206 sub subfield_is_koha_internal_p ($) {
209 # We could match on 'lib' and 'tab' (and 'mandatory', & more to come!)
210 # But real MARC subfields are always single-character
211 # so it really is safer just to check the length
213 return length $subfield != 1;
216 =head2 GetSupportName
218 $itemtypename = &GetSupportName($codestring);
220 Returns a string with the name of the itemtype.
227 return if (! $codestring);
229 my $advanced_search_types = C4::Context->preference("AdvancedSearchTypes");
230 if (!$advanced_search_types or $advanced_search_types eq 'itemtypes') {
237 my $sth = C4::Context->dbh->prepare($query);
238 $sth->execute($codestring);
239 ($resultstring)=$sth->fetchrow;
240 return $resultstring;
243 C4::Context->dbh->prepare(
244 "SELECT lib FROM authorised_values WHERE category = ? AND authorised_value = ?"
246 $sth->execute( $advanced_search_types, $codestring );
247 my $data = $sth->fetchrow_hashref;
248 return $$data{'lib'};
252 =head2 GetSupportList
254 $itemtypes = &GetSupportList();
256 Returns an array ref containing informations about Support (since itemtype is rather a circulation code when item-level-itypes is used).
258 build a HTML select with the following code :
260 =head3 in PERL SCRIPT
262 my $itemtypes = GetSupportList();
263 $template->param(itemtypeloop => $itemtypes);
267 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
268 <select name="itemtype">
269 <option value="">Default</option>
270 <!-- TMPL_LOOP name="itemtypeloop" -->
271 <option value="<!-- TMPL_VAR name="itemtype" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->> <!--TMPL_IF Name="imageurl"--><img alt="<!-- TMPL_VAR name="description" -->" src="<!--TMPL_VAR Name="imageurl"-->><!--TMPL_ELSE-->"<!-- TMPL_VAR name="description" --><!--/TMPL_IF--></option>
274 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
275 <input type="submit" value="OK" class="button">
281 my $advanced_search_types = C4::Context->preference("AdvancedSearchTypes");
282 if (!$advanced_search_types or $advanced_search_types eq 'itemtypes') {
288 my $sth = C4::Context->dbh->prepare($query);
290 return $sth->fetchall_arrayref({});
292 my $advsearchtypes = GetAuthorisedValues($advanced_search_types);
293 my @results= map {{itemtype=>$$_{authorised_value},description=>$$_{lib},imageurl=>$$_{imageurl}}} @$advsearchtypes;
299 $itemtypes = &GetItemTypes();
301 Returns information about existing itemtypes.
303 build a HTML select with the following code :
305 =head3 in PERL SCRIPT
307 my $itemtypes = GetItemTypes;
309 foreach my $thisitemtype (sort keys %$itemtypes) {
310 my $selected = 1 if $thisitemtype eq $itemtype;
311 my %row =(value => $thisitemtype,
312 selected => $selected,
313 description => $itemtypes->{$thisitemtype}->{'description'},
315 push @itemtypesloop, \%row;
317 $template->param(itemtypeloop => \@itemtypesloop);
321 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
322 <select name="itemtype">
323 <option value="">Default</option>
324 <!-- TMPL_LOOP name="itemtypeloop" -->
325 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="description" --></option>
328 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
329 <input type="submit" value="OK" class="button">
336 # returns a reference to a hash of references to itemtypes...
338 my $dbh = C4::Context->dbh;
343 my $sth = $dbh->prepare($query);
345 while ( my $IT = $sth->fetchrow_hashref ) {
346 $itemtypes{ $IT->{'itemtype'} } = $IT;
348 return ( \%itemtypes );
351 sub get_itemtypeinfos_of {
354 my $placeholders = join( ', ', map { '?' } @itemtypes );
355 my $query = <<"END_SQL";
361 WHERE itemtype IN ( $placeholders )
364 return get_infos_of( $query, 'itemtype', undef, \@itemtypes );
367 # this is temporary until we separate collection codes and item types
371 my $dbh = C4::Context->dbh;
374 "SELECT * FROM authorised_values ORDER BY authorised_value");
376 while ( my $data = $sth->fetchrow_hashref ) {
377 if ( $data->{category} eq "CCODE" ) {
379 $results[$count] = $data;
385 return ( $count, @results );
390 $authtypes = &getauthtypes();
392 Returns information about existing authtypes.
394 build a HTML select with the following code :
396 =head3 in PERL SCRIPT
398 my $authtypes = getauthtypes;
400 foreach my $thisauthtype (keys %$authtypes) {
401 my $selected = 1 if $thisauthtype eq $authtype;
402 my %row =(value => $thisauthtype,
403 selected => $selected,
404 authtypetext => $authtypes->{$thisauthtype}->{'authtypetext'},
406 push @authtypesloop, \%row;
408 $template->param(itemtypeloop => \@itemtypesloop);
412 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
413 <select name="authtype">
414 <!-- TMPL_LOOP name="authtypeloop" -->
415 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="authtypetext" --></option>
418 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
419 <input type="submit" value="OK" class="button">
427 # returns a reference to a hash of references to authtypes...
429 my $dbh = C4::Context->dbh;
430 my $sth = $dbh->prepare("select * from auth_types order by authtypetext");
432 while ( my $IT = $sth->fetchrow_hashref ) {
433 $authtypes{ $IT->{'authtypecode'} } = $IT;
435 return ( \%authtypes );
439 my ($authtypecode) = @_;
441 # returns a reference to a hash of references to authtypes...
443 my $dbh = C4::Context->dbh;
444 my $sth = $dbh->prepare("select * from auth_types where authtypecode=?");
445 $sth->execute($authtypecode);
446 my $res = $sth->fetchrow_hashref;
452 $frameworks = &getframework();
454 Returns information about existing frameworks
456 build a HTML select with the following code :
458 =head3 in PERL SCRIPT
460 my $frameworks = frameworks();
462 foreach my $thisframework (keys %$frameworks) {
463 my $selected = 1 if $thisframework eq $frameworkcode;
464 my %row =(value => $thisframework,
465 selected => $selected,
466 description => $frameworks->{$thisframework}->{'frameworktext'},
468 push @frameworksloop, \%row;
470 $template->param(frameworkloop => \@frameworksloop);
474 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
475 <select name="frameworkcode">
476 <option value="">Default</option>
477 <!-- TMPL_LOOP name="frameworkloop" -->
478 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="frameworktext" --></option>
481 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
482 <input type="submit" value="OK" class="button">
490 # returns a reference to a hash of references to branches...
492 my $dbh = C4::Context->dbh;
493 my $sth = $dbh->prepare("select * from biblio_framework");
495 while ( my $IT = $sth->fetchrow_hashref ) {
496 $itemtypes{ $IT->{'frameworkcode'} } = $IT;
498 return ( \%itemtypes );
501 =head2 getframeworkinfo
503 $frameworkinfo = &getframeworkinfo($frameworkcode);
505 Returns information about an frameworkcode.
509 sub getframeworkinfo {
510 my ($frameworkcode) = @_;
511 my $dbh = C4::Context->dbh;
513 $dbh->prepare("select * from biblio_framework where frameworkcode=?");
514 $sth->execute($frameworkcode);
515 my $res = $sth->fetchrow_hashref;
519 =head2 getitemtypeinfo
521 $itemtype = &getitemtype($itemtype);
523 Returns information about an itemtype.
527 sub getitemtypeinfo {
529 my $dbh = C4::Context->dbh;
530 my $sth = $dbh->prepare("select * from itemtypes where itemtype=?");
531 $sth->execute($itemtype);
532 my $res = $sth->fetchrow_hashref;
534 $res->{imageurl} = getitemtypeimagelocation( 'intranet', $res->{imageurl} );
539 =head2 getitemtypeimagedir
545 my $directory = getitemtypeimagedir( 'opac' );
547 pass in 'opac' or 'intranet'. Defaults to 'opac'.
549 returns the full path to the appropriate directory containing images.
555 sub getitemtypeimagedir {
556 my $src = shift || 'opac';
557 if ($src eq 'intranet') {
558 return C4::Context->config('intrahtdocs') . '/' .C4::Context->preference('template') . '/img/itemtypeimg';
560 return C4::Context->config('opachtdocs') . '/' . C4::Context->preference('template') . '/itemtypeimg';
564 sub getitemtypeimagesrc {
565 my $src = shift || 'opac';
566 if ($src eq 'intranet') {
567 return '/intranet-tmpl' . '/' . C4::Context->preference('template') . '/img/itemtypeimg';
569 return '/opac-tmpl' . '/' . C4::Context->preference('template') . '/itemtypeimg';
573 sub getitemtypeimagelocation($$) {
574 my ( $src, $image ) = @_;
576 return '' if ( !$image );
578 my $scheme = ( uri_split( $image ) )[0];
580 return $image if ( $scheme );
582 return getitemtypeimagesrc( $src ) . '/' . $image;
585 =head3 _getImagesFromDirectory
587 Find all of the image files in a directory in the filesystem
592 returns: a list of images in that directory.
594 Notes: this does not traverse into subdirectories. See
595 _getSubdirectoryNames for help with that.
596 Images are assumed to be files with .gif or .png file extensions.
597 The image names returned do not have the directory name on them.
601 sub _getImagesFromDirectory {
602 my $directoryname = shift;
603 return unless defined $directoryname;
604 return unless -d $directoryname;
606 if ( opendir ( my $dh, $directoryname ) ) {
607 my @images = grep { /\.(gif|png)$/i } readdir( $dh );
611 warn "unable to opendir $directoryname: $!";
616 =head3 _getSubdirectoryNames
618 Find all of the directories in a directory in the filesystem
623 returns: a list of subdirectories in that directory.
625 Notes: this does not traverse into subdirectories. Only the first
626 level of subdirectories are returned.
627 The directory names returned don't have the parent directory name
632 sub _getSubdirectoryNames {
633 my $directoryname = shift;
634 return unless defined $directoryname;
635 return unless -d $directoryname;
637 if ( opendir ( my $dh, $directoryname ) ) {
638 my @directories = grep { -d File::Spec->catfile( $directoryname, $_ ) && ! ( /^\./ ) } readdir( $dh );
642 warn "unable to opendir $directoryname: $!";
649 returns: a listref of hashrefs. Each hash represents another collection of images.
650 { imagesetname => 'npl', # the name of the image set (npl is the original one)
651 images => listref of image hashrefs
654 each image is represented by a hashref like this:
655 { KohaImage => 'npl/image.gif',
656 StaffImageUrl => '/intranet-tmpl/prog/img/itemtypeimg/npl/image.gif',
657 OpacImageURL => '/opac-tmpl/prog/itemtypeimg/npl/image.gif'
658 checked => 0 or 1: was this the image passed to this method?
659 Note: I'd like to remove this somehow.
666 my $checked = $params{'checked'} || '';
668 my $paths = { staff => { filesystem => getitemtypeimagedir('intranet'),
669 url => getitemtypeimagesrc('intranet'),
671 opac => { filesystem => getitemtypeimagedir('opac'),
672 url => getitemtypeimagesrc('opac'),
676 my @imagesets = (); # list of hasrefs of image set data to pass to template
677 my @subdirectories = _getSubdirectoryNames( $paths->{'staff'}{'filesystem'} );
679 foreach my $imagesubdir ( @subdirectories ) {
680 my @imagelist = (); # hashrefs of image info
681 my @imagenames = _getImagesFromDirectory( File::Spec->catfile( $paths->{'staff'}{'filesystem'}, $imagesubdir ) );
682 foreach my $thisimage ( @imagenames ) {
684 { KohaImage => "$imagesubdir/$thisimage",
685 StaffImageUrl => join( '/', $paths->{'staff'}{'url'}, $imagesubdir, $thisimage ),
686 OpacImageUrl => join( '/', $paths->{'opac'}{'url'}, $imagesubdir, $thisimage ),
687 checked => "$imagesubdir/$thisimage" eq $checked ? 1 : 0,
691 push @imagesets, { imagesetname => $imagesubdir,
692 images => \@imagelist };
700 $printers = &GetPrinters();
701 @queues = keys %$printers;
703 Returns information about existing printer queues.
705 C<$printers> is a reference-to-hash whose keys are the print queues
706 defined in the printers table of the Koha database. The values are
707 references-to-hash, whose keys are the fields in the printers table.
713 my $dbh = C4::Context->dbh;
714 my $sth = $dbh->prepare("select * from printers");
716 while ( my $printer = $sth->fetchrow_hashref ) {
717 $printers{ $printer->{'printqueue'} } = $printer;
719 return ( \%printers );
724 $printer = GetPrinter( $query, $printers );
728 sub GetPrinter ($$) {
729 my ( $query, $printers ) = @_; # get printer for this query from printers
730 my $printer = $query->param('printer');
731 my %cookie = $query->cookie('userenv');
732 ($printer) || ( $printer = $cookie{'printer'} ) || ( $printer = '' );
733 ( $printers->{$printer} ) || ( $printer = ( keys %$printers )[0] );
739 Returns the number of pages to display in a pagination bar, given the number
740 of items and the number of items per page.
745 my ( $nb_items, $nb_items_per_page ) = @_;
747 return int( ( $nb_items - 1 ) / $nb_items_per_page ) + 1;
752 (@themes) = &getallthemes('opac');
753 (@themes) = &getallthemes('intranet');
755 Returns an array of all available themes.
763 if ( $type eq 'intranet' ) {
764 $htdocs = C4::Context->config('intrahtdocs');
767 $htdocs = C4::Context->config('opachtdocs');
769 opendir D, "$htdocs";
770 my @dirlist = readdir D;
771 foreach my $directory (@dirlist) {
772 -d "$htdocs/$directory/en" and push @themes, $directory;
779 if ( C4::Context->preference("marcflavour") eq "UNIMARC" ) {
782 link_value => 'su-to',
783 label_value => 'Topics',
785 [ '600', '601', '602', '603', '604', '605', '606', '610' ],
789 link_value => 'su-geo',
790 label_value => 'Places',
795 link_value => 'su-ut',
796 label_value => 'Titles',
797 tags => [ '500', '501', '502', '503', '504', ],
802 label_value => 'Authors',
803 tags => [ '700', '701', '702', ],
808 label_value => 'Series',
817 link_value => 'branch',
818 label_value => 'Libraries',
823 push @$facets, $library_facet unless C4::Context->preference("singleBranchMode");
828 link_value => 'su-to',
829 label_value => 'Topics',
835 # link_value => 'su-na',
836 # label_value => 'People and Organizations',
837 # tags => ['600', '610', '611'],
841 link_value => 'su-geo',
842 label_value => 'Places',
847 link_value => 'su-ut',
848 label_value => 'Titles',
854 label_value => 'Authors',
855 tags => [ '100', '110', '700', ],
860 label_value => 'Series',
861 tags => [ '440', '490', ],
867 link_value => 'branch',
868 label_value => 'Libraries',
873 push @$facets, $library_facet unless C4::Context->preference("singleBranchMode");
880 Return a href where a key is associated to a href. You give a query,
881 the name of the key among the fields returned by the query. If you
882 also give as third argument the name of the value, the function
883 returns a href of scalar. The optional 4th argument is an arrayref of
884 items passed to the C<execute()> call. It is designed to bind
885 parameters to any placeholders in your SQL.
894 # generic href of any information on the item, href of href.
895 my $iteminfos_of = get_infos_of($query, 'itemnumber');
896 print $iteminfos_of->{$itemnumber}{barcode};
898 # specific information, href of scalar
899 my $barcode_of_item = get_infos_of($query, 'itemnumber', 'barcode');
900 print $barcode_of_item->{$itemnumber};
905 my ( $query, $key_name, $value_name, $bind_params ) = @_;
907 my $dbh = C4::Context->dbh;
909 my $sth = $dbh->prepare($query);
910 $sth->execute( @$bind_params );
913 while ( my $row = $sth->fetchrow_hashref ) {
914 if ( defined $value_name ) {
915 $infos_of{ $row->{$key_name} } = $row->{$value_name};
918 $infos_of{ $row->{$key_name} } = $row;
926 =head2 get_notforloan_label_of
928 my $notforloan_label_of = get_notforloan_label_of();
930 Each authorised value of notforloan (information available in items and
931 itemtypes) is link to a single label.
933 Returns a href where keys are authorised values and values are corresponding
936 foreach my $authorised_value (keys %{$notforloan_label_of}) {
938 "authorised_value: %s => %s\n",
940 $notforloan_label_of->{$authorised_value}
946 # FIXME - why not use GetAuthorisedValues ??
948 sub get_notforloan_label_of {
949 my $dbh = C4::Context->dbh;
952 SELECT authorised_value
953 FROM marc_subfield_structure
954 WHERE kohafield = \'items.notforloan\'
957 my $sth = $dbh->prepare($query);
959 my ($statuscode) = $sth->fetchrow_array();
964 FROM authorised_values
967 $sth = $dbh->prepare($query);
968 $sth->execute($statuscode);
969 my %notforloan_label_of;
970 while ( my $row = $sth->fetchrow_hashref ) {
971 $notforloan_label_of{ $row->{authorised_value} } = $row->{lib};
975 return \%notforloan_label_of;
978 =head2 displayServers
982 my $servers = displayServers();
984 my $servers = displayServers( $position );
986 my $servers = displayServers( $position, $type );
990 displayServers returns a listref of hashrefs, each containing
991 information about available z3950 servers. Each hashref has a format
995 'checked' => 'checked',
996 'encoding' => 'MARC-8'
998 'id' => 'LIBRARY OF CONGRESS',
1002 'value' => 'z3950.loc.gov:7090/',
1009 sub displayServers {
1010 my ( $position, $type ) = @_;
1011 my $dbh = C4::Context->dbh;
1013 my $strsth = 'SELECT * FROM z3950servers';
1018 push @bind_params, $position;
1019 push @where_clauses, ' position = ? ';
1023 push @bind_params, $type;
1024 push @where_clauses, ' type = ? ';
1027 # reassemble where clause from where clause pieces
1028 if (@where_clauses) {
1029 $strsth .= ' WHERE ' . join( ' AND ', @where_clauses );
1032 my $rq = $dbh->prepare($strsth);
1033 $rq->execute(@bind_params);
1034 my @primaryserverloop;
1036 while ( my $data = $rq->fetchrow_hashref ) {
1037 push @primaryserverloop,
1038 { label => $data->{description},
1039 id => $data->{name},
1041 value => $data->{host} . ":" . $data->{port} . "/" . $data->{database},
1042 encoding => ( $data->{encoding} ? $data->{encoding} : "iso-5426" ),
1043 checked => "checked",
1044 icon => $data->{icon},
1045 zed => $data->{type} eq 'zed',
1046 opensearch => $data->{type} eq 'opensearch'
1049 return \@primaryserverloop;
1052 =head2 GetAuthValCode
1054 $authvalcode = GetAuthValCode($kohafield,$frameworkcode);
1058 sub GetAuthValCode {
1059 my ($kohafield,$fwcode) = @_;
1060 my $dbh = C4::Context->dbh;
1061 $fwcode='' unless $fwcode;
1062 my $sth = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield=? and frameworkcode=?');
1063 $sth->execute($kohafield,$fwcode);
1064 my ($authvalcode) = $sth->fetchrow_array;
1065 return $authvalcode;
1068 =head2 GetAuthValCodeFromField
1070 $authvalcode = GetAuthValCodeFromField($field,$subfield,$frameworkcode);
1072 C<$subfield> can be undefined
1076 sub GetAuthValCodeFromField {
1077 my ($field,$subfield,$fwcode) = @_;
1078 my $dbh = C4::Context->dbh;
1079 $fwcode='' unless $fwcode;
1081 if (defined $subfield) {
1082 $sth = $dbh->prepare('select authorised_value from marc_subfield_structure where tagfield=? and tagsubfield=? and frameworkcode=?');
1083 $sth->execute($field,$subfield,$fwcode);
1085 $sth = $dbh->prepare('select authorised_value from marc_tag_structure where tagfield=? and frameworkcode=?');
1086 $sth->execute($field,$fwcode);
1088 my ($authvalcode) = $sth->fetchrow_array;
1089 return $authvalcode;
1092 =head2 GetAuthorisedValues
1094 $authvalues = GetAuthorisedValues([$category], [$selected]);
1096 This function returns all authorised values from the'authorised_value' table in a reference to array of hashrefs.
1098 C<$category> returns authorised values for just one category (optional).
1100 C<$opac> If set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1104 sub GetAuthorisedValues {
1105 my ($category,$selected,$opac) = @_;
1107 my $dbh = C4::Context->dbh;
1108 my $query = "SELECT * FROM authorised_values";
1109 $query .= " WHERE category = '" . $category . "'" if $category;
1110 $query .= " ORDER BY category, lib, lib_opac";
1111 my $sth = $dbh->prepare($query);
1113 while (my $data=$sth->fetchrow_hashref) {
1114 if ($selected && $selected eq $data->{'authorised_value'} ) {
1115 $data->{'selected'} = 1;
1117 if ($opac && $data->{'lib_opac'}) {
1118 $data->{'lib'} = $data->{'lib_opac'};
1120 push @results, $data;
1122 #my $data = $sth->fetchall_arrayref({});
1123 return \@results; #$data;
1126 =head2 GetAuthorisedValueCategories
1128 $auth_categories = GetAuthorisedValueCategories();
1130 Return an arrayref of all of the available authorised
1135 sub GetAuthorisedValueCategories {
1136 my $dbh = C4::Context->dbh;
1137 my $sth = $dbh->prepare("SELECT DISTINCT category FROM authorised_values ORDER BY category");
1140 while (my $category = $sth->fetchrow_array) {
1141 push @results, $category;
1146 =head2 GetKohaAuthorisedValues
1148 Takes $kohafield, $fwcode as parameters.
1149 If $opac parameter is set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1150 Returns hashref of Code => description
1152 if no authorised value category is defined for the kohafield.
1156 sub GetKohaAuthorisedValues {
1157 my ($kohafield,$fwcode,$opac) = @_;
1158 $fwcode='' unless $fwcode;
1160 my $dbh = C4::Context->dbh;
1161 my $avcode = GetAuthValCode($kohafield,$fwcode);
1163 my $sth = $dbh->prepare("select authorised_value, lib, lib_opac from authorised_values where category=? ");
1164 $sth->execute($avcode);
1165 while ( my ($val, $lib, $lib_opac) = $sth->fetchrow_array ) {
1166 $values{$val} = ($opac && $lib_opac) ? $lib_opac : $lib;
1174 =head2 GetKohaAuthorisedValuesFromField
1176 Takes $field, $subfield $fwcode as parameters.
1177 If $opac parameter is set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1178 $subfield can be undefined
1179 Returns hashref of Code => description
1181 if no authorised value category is defined for the given field and subfield
1185 sub GetKohaAuthorisedValuesFromField {
1186 my ($field, $subfield, $fwcode,$opac) = @_;
1187 $fwcode='' unless $fwcode;
1189 my $dbh = C4::Context->dbh;
1190 my $avcode = GetAuthValCodeFromField($field, $subfield, $fwcode);
1192 my $sth = $dbh->prepare("select authorised_value, lib, lib_opac from authorised_values where category=? ");
1193 $sth->execute($avcode);
1194 while ( my ($val, $lib, $lib_opac) = $sth->fetchrow_array ) {
1195 $values{$val} = ($opac && $lib_opac) ? $lib_opac : $lib;
1203 =head2 display_marc_indicators
1207 # field is a MARC::Field object
1208 my $display_form = C4::Koha::display_marc_indicators($field);
1212 Generate a display form of the indicators of a variable
1213 MARC field, replacing any blanks with '#'.
1217 sub display_marc_indicators {
1219 my $indicators = '';
1220 if ($field->tag() >= 10) {
1221 $indicators = $field->indicator(1) . $field->indicator(2);
1222 $indicators =~ s/ /#/g;
1227 sub GetNormalizedUPC {
1228 my ($record,$marcflavour) = @_;
1231 if ($marcflavour eq 'MARC21') {
1232 @fields = $record->field('024');
1233 foreach my $field (@fields) {
1234 my $indicator = $field->indicator(1);
1235 my $upc = _normalize_match_point($field->subfield('a'));
1236 if ($indicator == 1 and $upc ne '') {
1241 else { # assume unimarc if not marc21
1242 @fields = $record->field('072');
1243 foreach my $field (@fields) {
1244 my $upc = _normalize_match_point($field->subfield('a'));
1252 # Normalizes and returns the first valid ISBN found in the record
1253 sub GetNormalizedISBN {
1254 my ($isbn,$record,$marcflavour) = @_;
1257 return _isbn_cleanup($isbn);
1259 return undef unless $record;
1261 if ($marcflavour eq 'MARC21') {
1262 @fields = $record->field('020');
1263 foreach my $field (@fields) {
1264 $isbn = $field->subfield('a');
1266 return _isbn_cleanup($isbn);
1272 else { # assume unimarc if not marc21
1273 @fields = $record->field('010');
1274 foreach my $field (@fields) {
1275 my $isbn = $field->subfield('a');
1277 return _isbn_cleanup($isbn);
1286 sub GetNormalizedEAN {
1287 my ($record,$marcflavour) = @_;
1290 if ($marcflavour eq 'MARC21') {
1291 @fields = $record->field('024');
1292 foreach my $field (@fields) {
1293 my $indicator = $field->indicator(1);
1294 $ean = _normalize_match_point($field->subfield('a'));
1295 if ($indicator == 3 and $ean ne '') {
1300 else { # assume unimarc if not marc21
1301 @fields = $record->field('073');
1302 foreach my $field (@fields) {
1303 $ean = _normalize_match_point($field->subfield('a'));
1310 sub GetNormalizedOCLCNumber {
1311 my ($record,$marcflavour) = @_;
1314 if ($marcflavour eq 'MARC21') {
1315 @fields = $record->field('035');
1316 foreach my $field (@fields) {
1317 $oclc = $field->subfield('a');
1318 if ($oclc =~ /OCoLC/) {
1319 $oclc =~ s/\(OCoLC\)//;
1326 else { # TODO: add UNIMARC fields
1330 sub _normalize_match_point {
1331 my $match_point = shift;
1332 (my $normalized_match_point) = $match_point =~ /([\d-]*[X]*)/;
1333 $normalized_match_point =~ s/-//g;
1335 return $normalized_match_point;
1338 sub _isbn_cleanup ($) {
1339 my $normalized_isbn = shift;
1340 $normalized_isbn =~ s/-//g;
1341 $normalized_isbn =~/([0-9x]{1,})/i;
1342 $normalized_isbn = $1;
1344 $normalized_isbn =~ /\b(\d{13})\b/ or
1345 $normalized_isbn =~ /\b(\d{12})\b/i or
1346 $normalized_isbn =~ /\b(\d{10})\b/ or
1347 $normalized_isbn =~ /\b(\d{9}X)\b/i