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
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
60 &GetNormalizedOCLCNumber
68 memoize
('GetAuthorisedValues');
72 C4::Koha - Perl Module containing convenience functions for Koha scripts
81 Koha.pm provides many functions for Koha scripts.
89 $slash_date = &slashifyDate($dash_date);
91 Takes a string of the form "DD-MM-YYYY" (or anything separated by
92 dashes), converts it to the form "YYYY/MM/DD", and returns the result.
98 # accepts a date of the form xx-xx-xx[xx] and returns it in the
100 my @dateOut = split( '-', shift );
101 return ("$dateOut[2]/$dateOut[1]/$dateOut[0]");
107 my $string = DisplayISBN( $isbn );
113 if (length ($isbn)<13){
115 if ( substr( $isbn, 0, 1 ) <= 7 ) {
116 $seg1 = substr( $isbn, 0, 1 );
118 elsif ( substr( $isbn, 0, 2 ) <= 94 ) {
119 $seg1 = substr( $isbn, 0, 2 );
121 elsif ( substr( $isbn, 0, 3 ) <= 995 ) {
122 $seg1 = substr( $isbn, 0, 3 );
124 elsif ( substr( $isbn, 0, 4 ) <= 9989 ) {
125 $seg1 = substr( $isbn, 0, 4 );
128 $seg1 = substr( $isbn, 0, 5 );
130 my $x = substr( $isbn, length($seg1) );
132 if ( substr( $x, 0, 2 ) <= 19 ) {
134 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
135 $seg2 = substr( $x, 0, 2 );
137 elsif ( substr( $x, 0, 3 ) <= 699 ) {
138 $seg2 = substr( $x, 0, 3 );
140 elsif ( substr( $x, 0, 4 ) <= 8399 ) {
141 $seg2 = substr( $x, 0, 4 );
143 elsif ( substr( $x, 0, 5 ) <= 89999 ) {
144 $seg2 = substr( $x, 0, 5 );
146 elsif ( substr( $x, 0, 6 ) <= 9499999 ) {
147 $seg2 = substr( $x, 0, 6 );
150 $seg2 = substr( $x, 0, 7 );
152 my $seg3 = substr( $x, length($seg2) );
153 $seg3 = substr( $seg3, 0, length($seg3) - 1 );
154 my $seg4 = substr( $x, -1, 1 );
155 return "$seg1-$seg2-$seg3-$seg4";
158 $seg1 = substr( $isbn, 0, 3 );
160 if ( substr( $isbn, 3, 1 ) <= 7 ) {
161 $seg2 = substr( $isbn, 3, 1 );
163 elsif ( substr( $isbn, 3, 2 ) <= 94 ) {
164 $seg2 = substr( $isbn, 3, 2 );
166 elsif ( substr( $isbn, 3, 3 ) <= 995 ) {
167 $seg2 = substr( $isbn, 3, 3 );
169 elsif ( substr( $isbn, 3, 4 ) <= 9989 ) {
170 $seg2 = substr( $isbn, 3, 4 );
173 $seg2 = substr( $isbn, 3, 5 );
175 my $x = substr( $isbn, length($seg2) +3);
177 if ( substr( $x, 0, 2 ) <= 19 ) {
179 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
180 $seg3 = substr( $x, 0, 2 );
182 elsif ( substr( $x, 0, 3 ) <= 699 ) {
183 $seg3 = substr( $x, 0, 3 );
185 elsif ( substr( $x, 0, 4 ) <= 8399 ) {
186 $seg3 = substr( $x, 0, 4 );
188 elsif ( substr( $x, 0, 5 ) <= 89999 ) {
189 $seg3 = substr( $x, 0, 5 );
191 elsif ( substr( $x, 0, 6 ) <= 9499999 ) {
192 $seg3 = substr( $x, 0, 6 );
195 $seg3 = substr( $x, 0, 7 );
197 my $seg4 = substr( $x, length($seg3) );
198 $seg4 = substr( $seg4, 0, length($seg4) - 1 );
199 my $seg5 = substr( $x, -1, 1 );
200 return "$seg1-$seg2-$seg3-$seg4-$seg5";
204 # FIXME.. this should be moved to a MARC-specific module
205 sub subfield_is_koha_internal_p
($) {
208 # We could match on 'lib' and 'tab' (and 'mandatory', & more to come!)
209 # But real MARC subfields are always single-character
210 # so it really is safer just to check the length
212 return length $subfield != 1;
215 =head2 GetSupportName
217 $itemtypename = &GetSupportName($codestring);
219 Returns a string with the name of the itemtype.
226 return if (! $codestring);
228 my $advanced_search_types = C4
::Context
->preference("AdvancedSearchTypes");
229 if (!$advanced_search_types or $advanced_search_types eq 'itemtypes') {
236 my $sth = C4
::Context
->dbh->prepare($query);
237 $sth->execute($codestring);
238 ($resultstring)=$sth->fetchrow;
239 return $resultstring;
242 C4
::Context
->dbh->prepare(
243 "SELECT lib FROM authorised_values WHERE category = ? AND authorised_value = ?"
245 $sth->execute( $advanced_search_types, $codestring );
246 my $data = $sth->fetchrow_hashref;
247 return $$data{'lib'};
251 =head2 GetSupportList
253 $itemtypes = &GetSupportList();
255 Returns an array ref containing informations about Support (since itemtype is rather a circulation code when item-level-itypes is used).
257 build a HTML select with the following code :
259 =head3 in PERL SCRIPT
261 my $itemtypes = GetSupportList();
262 $template->param(itemtypeloop => $itemtypes);
266 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
267 <select name="itemtype">
268 <option value="">Default</option>
269 <!-- TMPL_LOOP name="itemtypeloop" -->
270 <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>
273 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
274 <input type="submit" value="OK" class="button">
280 my $advanced_search_types = C4
::Context
->preference("AdvancedSearchTypes");
281 if (!$advanced_search_types or $advanced_search_types eq 'itemtypes') {
287 my $sth = C4
::Context
->dbh->prepare($query);
289 return $sth->fetchall_arrayref({});
291 my $advsearchtypes = GetAuthorisedValues
($advanced_search_types);
292 my @results= map {{itemtype
=>$$_{authorised_value
},description
=>$$_{lib
},imageurl
=>$$_{imageurl
}}} @
$advsearchtypes;
298 $itemtypes = &GetItemTypes();
300 Returns information about existing itemtypes.
302 build a HTML select with the following code :
304 =head3 in PERL SCRIPT
306 my $itemtypes = GetItemTypes;
308 foreach my $thisitemtype (sort keys %$itemtypes) {
309 my $selected = 1 if $thisitemtype eq $itemtype;
310 my %row =(value => $thisitemtype,
311 selected => $selected,
312 description => $itemtypes->{$thisitemtype}->{'description'},
314 push @itemtypesloop, \%row;
316 $template->param(itemtypeloop => \@itemtypesloop);
320 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
321 <select name="itemtype">
322 <option value="">Default</option>
323 <!-- TMPL_LOOP name="itemtypeloop" -->
324 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="description" --></option>
327 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
328 <input type="submit" value="OK" class="button">
335 # returns a reference to a hash of references to itemtypes...
337 my $dbh = C4
::Context
->dbh;
342 my $sth = $dbh->prepare($query);
344 while ( my $IT = $sth->fetchrow_hashref ) {
345 $itemtypes{ $IT->{'itemtype'} } = $IT;
347 return ( \
%itemtypes );
350 sub get_itemtypeinfos_of
{
353 my $placeholders = join( ', ', map { '?' } @itemtypes );
354 my $query = <<"END_SQL";
360 WHERE itemtype IN ( $placeholders )
363 return get_infos_of( $query, 'itemtype', undef, \@itemtypes );
366 # this is temporary until we separate collection codes and item types
370 my $dbh = C4::Context->dbh;
373 "SELECT * FROM authorised_values ORDER BY authorised_value");
375 while ( my $data = $sth->fetchrow_hashref ) {
376 if ( $data->{category} eq "CCODE" ) {
378 $results[$count] = $data;
384 return ( $count, @results );
389 $authtypes = &getauthtypes();
391 Returns information about existing authtypes.
393 build a HTML select with the following code :
395 =head3 in PERL SCRIPT
397 my $authtypes = getauthtypes;
399 foreach my $thisauthtype (keys %$authtypes) {
400 my $selected = 1 if $thisauthtype eq $authtype;
401 my %row =(value => $thisauthtype,
402 selected => $selected,
403 authtypetext => $authtypes->{$thisauthtype}->{'authtypetext'},
405 push @authtypesloop, \%row;
407 $template->param(itemtypeloop => \@itemtypesloop);
411 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
412 <select name="authtype">
413 <!-- TMPL_LOOP name="authtypeloop" -->
414 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="authtypetext" --></option>
417 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
418 <input type="submit" value="OK" class="button">
426 # returns a reference to a hash of references to authtypes...
428 my $dbh = C4::Context->dbh;
429 my $sth = $dbh->prepare("select * from auth_types order by authtypetext");
431 while ( my $IT = $sth->fetchrow_hashref ) {
432 $authtypes{ $IT->{'authtypecode'} } = $IT;
434 return ( \%authtypes );
438 my ($authtypecode) = @_;
440 # returns a reference to a hash of references to authtypes...
442 my $dbh = C4::Context->dbh;
443 my $sth = $dbh->prepare("select * from auth_types where authtypecode=?");
444 $sth->execute($authtypecode);
445 my $res = $sth->fetchrow_hashref;
451 $frameworks = &getframework();
453 Returns information about existing frameworks
455 build a HTML select with the following code :
457 =head3 in PERL SCRIPT
459 my $frameworks = frameworks();
461 foreach my $thisframework (keys %$frameworks) {
462 my $selected = 1 if $thisframework eq $frameworkcode;
463 my %row =(value => $thisframework,
464 selected => $selected,
465 description => $frameworks->{$thisframework}->{'frameworktext'},
467 push @frameworksloop, \%row;
469 $template->param(frameworkloop => \@frameworksloop);
473 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
474 <select name="frameworkcode">
475 <option value="">Default</option>
476 <!-- TMPL_LOOP name="frameworkloop" -->
477 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="frameworktext" --></option>
480 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
481 <input type="submit" value="OK" class="button">
489 # returns a reference to a hash of references to branches...
491 my $dbh = C4::Context->dbh;
492 my $sth = $dbh->prepare("select * from biblio_framework");
494 while ( my $IT = $sth->fetchrow_hashref ) {
495 $itemtypes{ $IT->{'frameworkcode'} } = $IT;
497 return ( \%itemtypes );
500 =head2 getframeworkinfo
502 $frameworkinfo = &getframeworkinfo($frameworkcode);
504 Returns information about an frameworkcode.
508 sub getframeworkinfo {
509 my ($frameworkcode) = @_;
510 my $dbh = C4::Context->dbh;
512 $dbh->prepare("select * from biblio_framework where frameworkcode=?");
513 $sth->execute($frameworkcode);
514 my $res = $sth->fetchrow_hashref;
518 =head2 getitemtypeinfo
520 $itemtype = &getitemtype($itemtype);
522 Returns information about an itemtype.
526 sub getitemtypeinfo {
528 my $dbh = C4::Context->dbh;
529 my $sth = $dbh->prepare("select * from itemtypes where itemtype=?");
530 $sth->execute($itemtype);
531 my $res = $sth->fetchrow_hashref;
533 $res->{imageurl} = getitemtypeimagelocation( 'intranet', $res->{imageurl} );
538 =head2 getitemtypeimagedir
544 my $directory = getitemtypeimagedir( 'opac' );
546 pass in 'opac' or 'intranet'. Defaults to 'opac'.
548 returns the full path to the appropriate directory containing images.
554 sub getitemtypeimagedir {
555 my $src = shift || 'opac';
556 if ($src eq 'intranet') {
557 return C4::Context->config('intrahtdocs') . '/' .C4::Context->preference('template') . '/img/itemtypeimg';
559 return C4::Context->config('opachtdocs') . '/' . C4::Context->preference('template') . '/itemtypeimg';
563 sub getitemtypeimagesrc {
564 my $src = shift || 'opac';
565 if ($src eq 'intranet') {
566 return '/intranet-tmpl' . '/' . C4::Context->preference('template') . '/img/itemtypeimg';
568 return '/opac-tmpl' . '/' . C4::Context->preference('template') . '/itemtypeimg';
572 sub getitemtypeimagelocation($$) {
573 my ( $src, $image ) = @_;
575 return '' if ( !$image );
577 my $scheme = ( uri_split( $image ) )[0];
579 return $image if ( $scheme );
581 return getitemtypeimagesrc( $src ) . '/' . $image;
584 =head3 _getImagesFromDirectory
586 Find all of the image files in a directory in the filesystem
591 returns: a list of images in that directory.
593 Notes: this does not traverse into subdirectories. See
594 _getSubdirectoryNames for help with that.
595 Images are assumed to be files with .gif or .png file extensions.
596 The image names returned do not have the directory name on them.
600 sub _getImagesFromDirectory {
601 my $directoryname = shift;
602 return unless defined $directoryname;
603 return unless -d $directoryname;
605 if ( opendir ( my $dh, $directoryname ) ) {
606 my @images = grep { /\.(gif|png)$/i } readdir( $dh );
610 warn "unable to opendir $directoryname: $!";
615 =head3 _getSubdirectoryNames
617 Find all of the directories in a directory in the filesystem
622 returns: a list of subdirectories in that directory.
624 Notes: this does not traverse into subdirectories. Only the first
625 level of subdirectories are returned.
626 The directory names returned don't have the parent directory name
631 sub _getSubdirectoryNames {
632 my $directoryname = shift;
633 return unless defined $directoryname;
634 return unless -d $directoryname;
636 if ( opendir ( my $dh, $directoryname ) ) {
637 my @directories = grep { -d File::Spec->catfile( $directoryname, $_ ) && ! ( /^\./ ) } readdir( $dh );
641 warn "unable to opendir $directoryname: $!";
648 returns: a listref of hashrefs. Each hash represents another collection of images.
649 { imagesetname => 'npl', # the name of the image set (npl is the original one)
650 images => listref of image hashrefs
653 each image is represented by a hashref like this:
654 { KohaImage => 'npl/image.gif',
655 StaffImageUrl => '/intranet-tmpl/prog/img/itemtypeimg/npl/image.gif',
656 OpacImageURL => '/opac-tmpl/prog/itemtypeimg/npl/image.gif'
657 checked => 0 or 1: was this the image passed to this method?
658 Note: I'd like to remove this somehow.
665 my $checked = $params{'checked'} || '';
667 my $paths = { staff => { filesystem => getitemtypeimagedir('intranet'),
668 url => getitemtypeimagesrc('intranet'),
670 opac => { filesystem => getitemtypeimagedir('opac'),
671 url => getitemtypeimagesrc('opac'),
675 my @imagesets = (); # list of hasrefs of image set data to pass to template
676 my @subdirectories = _getSubdirectoryNames( $paths->{'staff'}{'filesystem'} );
678 foreach my $imagesubdir ( @subdirectories ) {
679 my @imagelist = (); # hashrefs of image info
680 my @imagenames = _getImagesFromDirectory( File::Spec->catfile( $paths->{'staff'}{'filesystem'}, $imagesubdir ) );
681 foreach my $thisimage ( @imagenames ) {
683 { KohaImage => "$imagesubdir/$thisimage",
684 StaffImageUrl => join( '/', $paths->{'staff'}{'url'}, $imagesubdir, $thisimage ),
685 OpacImageUrl => join( '/', $paths->{'opac'}{'url'}, $imagesubdir, $thisimage ),
686 checked => "$imagesubdir/$thisimage" eq $checked ? 1 : 0,
690 push @imagesets, { imagesetname => $imagesubdir,
691 images => \@imagelist };
699 $printers = &GetPrinters();
700 @queues = keys %$printers;
702 Returns information about existing printer queues.
704 C<$printers> is a reference-to-hash whose keys are the print queues
705 defined in the printers table of the Koha database. The values are
706 references-to-hash, whose keys are the fields in the printers table.
712 my $dbh = C4::Context->dbh;
713 my $sth = $dbh->prepare("select * from printers");
715 while ( my $printer = $sth->fetchrow_hashref ) {
716 $printers{ $printer->{'printqueue'} } = $printer;
718 return ( \%printers );
723 $printer = GetPrinter( $query, $printers );
727 sub GetPrinter ($$) {
728 my ( $query, $printers ) = @_; # get printer for this query from printers
729 my $printer = $query->param('printer');
730 my %cookie = $query->cookie('userenv');
731 ($printer) || ( $printer = $cookie{'printer'} ) || ( $printer = '' );
732 ( $printers->{$printer} ) || ( $printer = ( keys %$printers )[0] );
738 Returns the number of pages to display in a pagination bar, given the number
739 of items and the number of items per page.
744 my ( $nb_items, $nb_items_per_page ) = @_;
746 return int( ( $nb_items - 1 ) / $nb_items_per_page ) + 1;
751 (@themes) = &getallthemes('opac');
752 (@themes) = &getallthemes('intranet');
754 Returns an array of all available themes.
762 if ( $type eq 'intranet' ) {
763 $htdocs = C4::Context->config('intrahtdocs');
766 $htdocs = C4::Context->config('opachtdocs');
768 opendir D, "$htdocs";
769 my @dirlist = readdir D;
770 foreach my $directory (@dirlist) {
771 -d "$htdocs/$directory/en" and push @themes, $directory;
778 if ( C4::Context->preference("marcflavour") eq "UNIMARC" ) {
781 link_value => 'su-to',
782 label_value => 'Topics',
784 [ '600', '601', '602', '603', '604', '605', '606', '610' ],
788 link_value => 'su-geo',
789 label_value => 'Places',
794 link_value => 'su-ut',
795 label_value => 'Titles',
796 tags => [ '500', '501', '502', '503', '504', ],
801 label_value => 'Authors',
802 tags => [ '700', '701', '702', ],
807 label_value => 'Series',
816 link_value => 'branch',
817 label_value => 'Libraries',
822 push @$facets, $library_facet unless C4::Context->preference("singleBranchMode");
827 link_value => 'su-to',
828 label_value => 'Topics',
834 # link_value => 'su-na',
835 # label_value => 'People and Organizations',
836 # tags => ['600', '610', '611'],
840 link_value => 'su-geo',
841 label_value => 'Places',
846 link_value => 'su-ut',
847 label_value => 'Titles',
853 label_value => 'Authors',
854 tags => [ '100', '110', '700', ],
859 label_value => 'Series',
860 tags => [ '440', '490', ],
866 link_value => 'branch',
867 label_value => 'Libraries',
872 push @$facets, $library_facet unless C4::Context->preference("singleBranchMode");
879 Return a href where a key is associated to a href. You give a query,
880 the name of the key among the fields returned by the query. If you
881 also give as third argument the name of the value, the function
882 returns a href of scalar. The optional 4th argument is an arrayref of
883 items passed to the C<execute()> call. It is designed to bind
884 parameters to any placeholders in your SQL.
893 # generic href of any information on the item, href of href.
894 my $iteminfos_of = get_infos_of($query, 'itemnumber');
895 print $iteminfos_of->{$itemnumber}{barcode};
897 # specific information, href of scalar
898 my $barcode_of_item = get_infos_of($query, 'itemnumber', 'barcode');
899 print $barcode_of_item->{$itemnumber};
904 my ( $query, $key_name, $value_name, $bind_params ) = @_;
906 my $dbh = C4::Context->dbh;
908 my $sth = $dbh->prepare($query);
909 $sth->execute( @$bind_params );
912 while ( my $row = $sth->fetchrow_hashref ) {
913 if ( defined $value_name ) {
914 $infos_of{ $row->{$key_name} } = $row->{$value_name};
917 $infos_of{ $row->{$key_name} } = $row;
925 =head2 get_notforloan_label_of
927 my $notforloan_label_of = get_notforloan_label_of();
929 Each authorised value of notforloan (information available in items and
930 itemtypes) is link to a single label.
932 Returns a href where keys are authorised values and values are corresponding
935 foreach my $authorised_value (keys %{$notforloan_label_of}) {
937 "authorised_value: %s => %s\n",
939 $notforloan_label_of->{$authorised_value}
945 # FIXME - why not use GetAuthorisedValues ??
947 sub get_notforloan_label_of {
948 my $dbh = C4::Context->dbh;
951 SELECT authorised_value
952 FROM marc_subfield_structure
953 WHERE kohafield = \'items.notforloan\'
956 my $sth = $dbh->prepare($query);
958 my ($statuscode) = $sth->fetchrow_array();
963 FROM authorised_values
966 $sth = $dbh->prepare($query);
967 $sth->execute($statuscode);
968 my %notforloan_label_of;
969 while ( my $row = $sth->fetchrow_hashref ) {
970 $notforloan_label_of{ $row->{authorised_value} } = $row->{lib};
974 return \%notforloan_label_of;
977 =head2 displayServers
981 my $servers = displayServers();
983 my $servers = displayServers( $position );
985 my $servers = displayServers( $position, $type );
989 displayServers returns a listref of hashrefs, each containing
990 information about available z3950 servers. Each hashref has a format
994 'checked' => 'checked',
995 'encoding' => 'MARC-8'
997 'id' => 'LIBRARY OF CONGRESS',
1001 'value' => 'z3950.loc.gov:7090/',
1008 sub displayServers {
1009 my ( $position, $type ) = @_;
1010 my $dbh = C4::Context->dbh;
1012 my $strsth = 'SELECT * FROM z3950servers';
1017 push @bind_params, $position;
1018 push @where_clauses, ' position = ? ';
1022 push @bind_params, $type;
1023 push @where_clauses, ' type = ? ';
1026 # reassemble where clause from where clause pieces
1027 if (@where_clauses) {
1028 $strsth .= ' WHERE ' . join( ' AND ', @where_clauses );
1031 my $rq = $dbh->prepare($strsth);
1032 $rq->execute(@bind_params);
1033 my @primaryserverloop;
1035 while ( my $data = $rq->fetchrow_hashref ) {
1036 push @primaryserverloop,
1037 { label => $data->{description},
1038 id => $data->{name},
1040 value => $data->{host} . ":" . $data->{port} . "/" . $data->{database},
1041 encoding => ( $data->{encoding} ? $data->{encoding} : "iso-5426" ),
1042 checked => "checked",
1043 icon => $data->{icon},
1044 zed => $data->{type} eq 'zed',
1045 opensearch => $data->{type} eq 'opensearch'
1048 return \@primaryserverloop;
1051 =head2 GetAuthValCode
1053 $authvalcode = GetAuthValCode($kohafield,$frameworkcode);
1057 sub GetAuthValCode {
1058 my ($kohafield,$fwcode) = @_;
1059 my $dbh = C4::Context->dbh;
1060 $fwcode='' unless $fwcode;
1061 my $sth = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield=? and frameworkcode=?');
1062 $sth->execute($kohafield,$fwcode);
1063 my ($authvalcode) = $sth->fetchrow_array;
1064 return $authvalcode;
1067 =head2 GetAuthorisedValues
1069 $authvalues = GetAuthorisedValues([$category], [$selected]);
1071 This function returns all authorised values from the'authorised_value' table in a reference to array of hashrefs.
1073 C<$category> returns authorised values for just one category (optional).
1075 C<$opac> If set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1079 sub GetAuthorisedValues {
1080 my ($category,$selected,$opac) = @_;
1082 my $dbh = C4::Context->dbh;
1083 my $query = "SELECT * FROM authorised_values";
1084 $query .= " WHERE category = '" . $category . "'" if $category;
1085 $query .= " ORDER BY category, lib, lib_opac";
1086 my $sth = $dbh->prepare($query);
1088 while (my $data=$sth->fetchrow_hashref) {
1089 if ($selected eq $data->{'authorised_value'} ) {
1090 $data->{'selected'} = 1;
1092 if ($opac && $data->{'lib_opac'}) {
1093 $data->{'lib'} = $data->{'lib_opac'};
1095 push @results, $data;
1097 #my $data = $sth->fetchall_arrayref({});
1098 return \@results; #$data;
1101 =head2 GetAuthorisedValueCategories
1103 $auth_categories = GetAuthorisedValueCategories();
1105 Return an arrayref of all of the available authorised
1110 sub GetAuthorisedValueCategories {
1111 my $dbh = C4::Context->dbh;
1112 my $sth = $dbh->prepare("SELECT DISTINCT category FROM authorised_values ORDER BY category");
1115 while (my $category = $sth->fetchrow_array) {
1116 push @results, $category;
1121 =head2 GetKohaAuthorisedValues
1123 Takes $kohafield, $fwcode as parameters.
1124 If $opac parameter is set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1125 Returns hashref of Code => description
1127 if no authorised value category is defined for the kohafield.
1131 sub GetKohaAuthorisedValues {
1132 my ($kohafield,$fwcode,$opac) = @_;
1133 $fwcode='' unless $fwcode;
1135 my $dbh = C4::Context->dbh;
1136 my $avcode = GetAuthValCode($kohafield,$fwcode);
1138 my $sth = $dbh->prepare("select authorised_value, lib, lib_opac from authorised_values where category=? ");
1139 $sth->execute($avcode);
1140 while ( my ($val, $lib, $lib_opac) = $sth->fetchrow_array ) {
1141 $values{$val} = ($opac && $lib_opac) ? $lib_opac : $lib;
1149 =head2 display_marc_indicators
1153 # field is a MARC::Field object
1154 my $display_form = C4::Koha::display_marc_indicators($field);
1158 Generate a display form of the indicators of a variable
1159 MARC field, replacing any blanks with '#'.
1163 sub display_marc_indicators {
1165 my $indicators = '';
1166 if ($field->tag() >= 10) {
1167 $indicators = $field->indicator(1) . $field->indicator(2);
1168 $indicators =~ s/ /#/g;
1173 sub GetNormalizedUPC {
1174 my ($record,$marcflavour) = @_;
1177 if ($marcflavour eq 'MARC21') {
1178 @fields = $record->field('024');
1179 foreach my $field (@fields) {
1180 my $indicator = $field->indicator(1);
1181 my $upc = _normalize_match_point($field->subfield('a'));
1182 if ($indicator == 1 and $upc ne '') {
1187 else { # assume unimarc if not marc21
1188 @fields = $record->field('072');
1189 foreach my $field (@fields) {
1190 my $upc = _normalize_match_point($field->subfield('a'));
1198 # Normalizes and returns the first valid ISBN found in the record
1199 sub GetNormalizedISBN {
1200 my ($isbn,$record,$marcflavour) = @_;
1203 return _isbn_cleanup($isbn);
1205 return undef unless $record;
1207 if ($marcflavour eq 'MARC21') {
1208 @fields = $record->field('020');
1209 foreach my $field (@fields) {
1210 $isbn = $field->subfield('a');
1212 return _isbn_cleanup($isbn);
1218 else { # assume unimarc if not marc21
1219 @fields = $record->field('010');
1220 foreach my $field (@fields) {
1221 my $isbn = $field->subfield('a');
1223 return _isbn_cleanup($isbn);
1232 sub GetNormalizedEAN {
1233 my ($record,$marcflavour) = @_;
1236 if ($marcflavour eq 'MARC21') {
1237 @fields = $record->field('024');
1238 foreach my $field (@fields) {
1239 my $indicator = $field->indicator(1);
1240 $ean = _normalize_match_point($field->subfield('a'));
1241 if ($indicator == 3 and $ean ne '') {
1246 else { # assume unimarc if not marc21
1247 @fields = $record->field('073');
1248 foreach my $field (@fields) {
1249 $ean = _normalize_match_point($field->subfield('a'));
1256 sub GetNormalizedOCLCNumber {
1257 my ($record,$marcflavour) = @_;
1260 if ($marcflavour eq 'MARC21') {
1261 @fields = $record->field('035');
1262 foreach my $field (@fields) {
1263 $oclc = $field->subfield('a');
1264 if ($oclc =~ /OCoLC/) {
1265 $oclc =~ s/\(OCoLC\)//;
1272 else { # TODO: add UNIMARC fields
1276 sub _normalize_match_point {
1277 my $match_point = shift;
1278 (my $normalized_match_point) = $match_point =~ /([\d-]*[X]*)/;
1279 $normalized_match_point =~ s/-//g;
1281 return $normalized_match_point;
1284 sub _isbn_cleanup ($) {
1285 my $normalized_isbn = shift;
1286 $normalized_isbn =~ s/-//g;
1287 $normalized_isbn =~/([0-9x]{1,})/i;
1288 $normalized_isbn = $1;
1290 $normalized_isbn =~ /\b(\d{13})\b/ or
1291 $normalized_isbn =~ /\b(\d{12})\b/i or
1292 $normalized_isbn =~ /\b(\d{10})\b/ or
1293 $normalized_isbn =~ /\b(\d{9}X)\b/i