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);
26 use vars qw($VERSION @ISA @EXPORT $DEBUG);
35 &subfield_is_koha_internal_p
36 &GetPrinters &GetPrinter
37 &GetItemTypes &getitemtypeinfo
40 &getframeworks &getframeworkinfo
41 &getauthtypes &getauthtype
47 &get_notforloan_label_of
50 &getitemtypeimagelocation
52 &GetAuthorisedValueCategories
53 &GetKohaAuthorisedValues
55 &GetManagedTagSubfields
59 &GetNormalizedOCLCNumber
68 C4::Koha - Perl Module containing convenience functions for Koha scripts
77 Koha.pm provides many functions for Koha scripts.
85 $slash_date = &slashifyDate($dash_date);
87 Takes a string of the form "DD-MM-YYYY" (or anything separated by
88 dashes), converts it to the form "YYYY/MM/DD", and returns the result.
94 # accepts a date of the form xx-xx-xx[xx] and returns it in the
96 my @dateOut = split( '-', shift );
97 return ("$dateOut[2]/$dateOut[1]/$dateOut[0]");
103 my $string = DisplayISBN( $isbn );
109 if (length ($isbn)<13){
111 if ( substr( $isbn, 0, 1 ) <= 7 ) {
112 $seg1 = substr( $isbn, 0, 1 );
114 elsif ( substr( $isbn, 0, 2 ) <= 94 ) {
115 $seg1 = substr( $isbn, 0, 2 );
117 elsif ( substr( $isbn, 0, 3 ) <= 995 ) {
118 $seg1 = substr( $isbn, 0, 3 );
120 elsif ( substr( $isbn, 0, 4 ) <= 9989 ) {
121 $seg1 = substr( $isbn, 0, 4 );
124 $seg1 = substr( $isbn, 0, 5 );
126 my $x = substr( $isbn, length($seg1) );
128 if ( substr( $x, 0, 2 ) <= 19 ) {
130 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
131 $seg2 = substr( $x, 0, 2 );
133 elsif ( substr( $x, 0, 3 ) <= 699 ) {
134 $seg2 = substr( $x, 0, 3 );
136 elsif ( substr( $x, 0, 4 ) <= 8399 ) {
137 $seg2 = substr( $x, 0, 4 );
139 elsif ( substr( $x, 0, 5 ) <= 89999 ) {
140 $seg2 = substr( $x, 0, 5 );
142 elsif ( substr( $x, 0, 6 ) <= 9499999 ) {
143 $seg2 = substr( $x, 0, 6 );
146 $seg2 = substr( $x, 0, 7 );
148 my $seg3 = substr( $x, length($seg2) );
149 $seg3 = substr( $seg3, 0, length($seg3) - 1 );
150 my $seg4 = substr( $x, -1, 1 );
151 return "$seg1-$seg2-$seg3-$seg4";
154 $seg1 = substr( $isbn, 0, 3 );
156 if ( substr( $isbn, 3, 1 ) <= 7 ) {
157 $seg2 = substr( $isbn, 3, 1 );
159 elsif ( substr( $isbn, 3, 2 ) <= 94 ) {
160 $seg2 = substr( $isbn, 3, 2 );
162 elsif ( substr( $isbn, 3, 3 ) <= 995 ) {
163 $seg2 = substr( $isbn, 3, 3 );
165 elsif ( substr( $isbn, 3, 4 ) <= 9989 ) {
166 $seg2 = substr( $isbn, 3, 4 );
169 $seg2 = substr( $isbn, 3, 5 );
171 my $x = substr( $isbn, length($seg2) +3);
173 if ( substr( $x, 0, 2 ) <= 19 ) {
175 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
176 $seg3 = substr( $x, 0, 2 );
178 elsif ( substr( $x, 0, 3 ) <= 699 ) {
179 $seg3 = substr( $x, 0, 3 );
181 elsif ( substr( $x, 0, 4 ) <= 8399 ) {
182 $seg3 = substr( $x, 0, 4 );
184 elsif ( substr( $x, 0, 5 ) <= 89999 ) {
185 $seg3 = substr( $x, 0, 5 );
187 elsif ( substr( $x, 0, 6 ) <= 9499999 ) {
188 $seg3 = substr( $x, 0, 6 );
191 $seg3 = substr( $x, 0, 7 );
193 my $seg4 = substr( $x, length($seg3) );
194 $seg4 = substr( $seg4, 0, length($seg4) - 1 );
195 my $seg5 = substr( $x, -1, 1 );
196 return "$seg1-$seg2-$seg3-$seg4-$seg5";
200 # FIXME.. this should be moved to a MARC-specific module
201 sub subfield_is_koha_internal_p ($) {
204 # We could match on 'lib' and 'tab' (and 'mandatory', & more to come!)
205 # But real MARC subfields are always single-character
206 # so it really is safer just to check the length
208 return length $subfield != 1;
213 $itemtypes = &GetItemTypes();
215 Returns information about existing itemtypes.
217 build a HTML select with the following code :
219 =head3 in PERL SCRIPT
221 my $itemtypes = GetItemTypes;
223 foreach my $thisitemtype (sort keys %$itemtypes) {
224 my $selected = 1 if $thisitemtype eq $itemtype;
225 my %row =(value => $thisitemtype,
226 selected => $selected,
227 description => $itemtypes->{$thisitemtype}->{'description'},
229 push @itemtypesloop, \%row;
231 $template->param(itemtypeloop => \@itemtypesloop);
235 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
236 <select name="itemtype">
237 <option value="">Default</option>
238 <!-- TMPL_LOOP name="itemtypeloop" -->
239 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="description" --></option>
242 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
243 <input type="submit" value="OK" class="button">
250 # returns a reference to a hash of references to itemtypes...
252 my $dbh = C4::Context->dbh;
257 my $sth = $dbh->prepare($query);
259 while ( my $IT = $sth->fetchrow_hashref ) {
260 $itemtypes{ $IT->{'itemtype'} } = $IT;
262 return ( \%itemtypes );
265 sub get_itemtypeinfos_of {
268 my $placeholders = join( ', ', map { '?' } @itemtypes );
269 my $query = <<"END_SQL";
275 WHERE itemtype IN ( $placeholders )
278 return get_infos_of( $query, 'itemtype', undef, \@itemtypes );
281 # this is temporary until we separate collection codes and item types
285 my $dbh = C4::Context->dbh;
288 "SELECT * FROM authorised_values ORDER BY authorised_value");
290 while ( my $data = $sth->fetchrow_hashref ) {
291 if ( $data->{category} eq "CCODE" ) {
293 $results[$count] = $data;
299 return ( $count, @results );
304 $authtypes = &getauthtypes();
306 Returns information about existing authtypes.
308 build a HTML select with the following code :
310 =head3 in PERL SCRIPT
312 my $authtypes = getauthtypes;
314 foreach my $thisauthtype (keys %$authtypes) {
315 my $selected = 1 if $thisauthtype eq $authtype;
316 my %row =(value => $thisauthtype,
317 selected => $selected,
318 authtypetext => $authtypes->{$thisauthtype}->{'authtypetext'},
320 push @authtypesloop, \%row;
322 $template->param(itemtypeloop => \@itemtypesloop);
326 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
327 <select name="authtype">
328 <!-- TMPL_LOOP name="authtypeloop" -->
329 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="authtypetext" --></option>
332 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
333 <input type="submit" value="OK" class="button">
341 # returns a reference to a hash of references to authtypes...
343 my $dbh = C4::Context->dbh;
344 my $sth = $dbh->prepare("select * from auth_types order by authtypetext");
346 while ( my $IT = $sth->fetchrow_hashref ) {
347 $authtypes{ $IT->{'authtypecode'} } = $IT;
349 return ( \%authtypes );
353 my ($authtypecode) = @_;
355 # returns a reference to a hash of references to authtypes...
357 my $dbh = C4::Context->dbh;
358 my $sth = $dbh->prepare("select * from auth_types where authtypecode=?");
359 $sth->execute($authtypecode);
360 my $res = $sth->fetchrow_hashref;
366 $frameworks = &getframework();
368 Returns information about existing frameworks
370 build a HTML select with the following code :
372 =head3 in PERL SCRIPT
374 my $frameworks = frameworks();
376 foreach my $thisframework (keys %$frameworks) {
377 my $selected = 1 if $thisframework eq $frameworkcode;
378 my %row =(value => $thisframework,
379 selected => $selected,
380 description => $frameworks->{$thisframework}->{'frameworktext'},
382 push @frameworksloop, \%row;
384 $template->param(frameworkloop => \@frameworksloop);
388 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
389 <select name="frameworkcode">
390 <option value="">Default</option>
391 <!-- TMPL_LOOP name="frameworkloop" -->
392 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="frameworktext" --></option>
395 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
396 <input type="submit" value="OK" class="button">
404 # returns a reference to a hash of references to branches...
406 my $dbh = C4::Context->dbh;
407 my $sth = $dbh->prepare("select * from biblio_framework");
409 while ( my $IT = $sth->fetchrow_hashref ) {
410 $itemtypes{ $IT->{'frameworkcode'} } = $IT;
412 return ( \%itemtypes );
415 =head2 getframeworkinfo
417 $frameworkinfo = &getframeworkinfo($frameworkcode);
419 Returns information about an frameworkcode.
423 sub getframeworkinfo {
424 my ($frameworkcode) = @_;
425 my $dbh = C4::Context->dbh;
427 $dbh->prepare("select * from biblio_framework where frameworkcode=?");
428 $sth->execute($frameworkcode);
429 my $res = $sth->fetchrow_hashref;
433 =head2 getitemtypeinfo
435 $itemtype = &getitemtype($itemtype);
437 Returns information about an itemtype.
441 sub getitemtypeinfo {
443 my $dbh = C4::Context->dbh;
444 my $sth = $dbh->prepare("select * from itemtypes where itemtype=?");
445 $sth->execute($itemtype);
446 my $res = $sth->fetchrow_hashref;
448 $res->{imageurl} = getitemtypeimagelocation( 'intranet', $res->{imageurl} );
453 =head2 getitemtypeimagedir
459 my $directory = getitemtypeimagedir( 'opac' );
461 pass in 'opac' or 'intranet'. Defaults to 'opac'.
463 returns the full path to the appropriate directory containing images.
469 sub getitemtypeimagedir {
470 my $src = shift || 'opac';
471 if ($src eq 'intranet') {
472 return C4::Context->config('intrahtdocs') . '/' .C4::Context->preference('template') . '/img/itemtypeimg';
474 return C4::Context->config('opachtdocs') . '/' . C4::Context->preference('template') . '/itemtypeimg';
478 sub getitemtypeimagesrc {
479 my $src = shift || 'opac';
480 if ($src eq 'intranet') {
481 return '/intranet-tmpl' . '/' . C4::Context->preference('template') . '/img/itemtypeimg';
483 return '/opac-tmpl' . '/' . C4::Context->preference('template') . '/itemtypeimg';
487 sub getitemtypeimagelocation($$) {
488 my ( $src, $image ) = @_;
490 return '' if ( !$image );
492 my $scheme = ( uri_split( $image ) )[0];
494 return $image if ( $scheme );
496 return getitemtypeimagesrc( $src ) . '/' . $image;
499 =head3 _getImagesFromDirectory
501 Find all of the image files in a directory in the filesystem
506 returns: a list of images in that directory.
508 Notes: this does not traverse into subdirectories. See
509 _getSubdirectoryNames for help with that.
510 Images are assumed to be files with .gif or .png file extensions.
511 The image names returned do not have the directory name on them.
515 sub _getImagesFromDirectory {
516 my $directoryname = shift;
517 return unless defined $directoryname;
518 return unless -d $directoryname;
520 if ( opendir ( my $dh, $directoryname ) ) {
521 my @images = grep { /\.(gif|png)$/i } readdir( $dh );
525 warn "unable to opendir $directoryname: $!";
530 =head3 _getSubdirectoryNames
532 Find all of the directories in a directory in the filesystem
537 returns: a list of subdirectories in that directory.
539 Notes: this does not traverse into subdirectories. Only the first
540 level of subdirectories are returned.
541 The directory names returned don't have the parent directory name
546 sub _getSubdirectoryNames {
547 my $directoryname = shift;
548 return unless defined $directoryname;
549 return unless -d $directoryname;
551 if ( opendir ( my $dh, $directoryname ) ) {
552 my @directories = grep { -d File::Spec->catfile( $directoryname, $_ ) && ! ( /^\./ ) } readdir( $dh );
556 warn "unable to opendir $directoryname: $!";
563 returns: a listref of hashrefs. Each hash represents another collection of images.
564 { imagesetname => 'npl', # the name of the image set (npl is the original one)
565 images => listref of image hashrefs
568 each image is represented by a hashref like this:
569 { KohaImage => 'npl/image.gif',
570 StaffImageUrl => '/intranet-tmpl/prog/img/itemtypeimg/npl/image.gif',
571 OpacImageURL => '/opac-tmpl/prog/itemtypeimg/npl/image.gif'
572 checked => 0 or 1: was this the image passed to this method?
573 Note: I'd like to remove this somehow.
580 my $checked = $params{'checked'} || '';
582 my $paths = { staff => { filesystem => getitemtypeimagedir('intranet'),
583 url => getitemtypeimagesrc('intranet'),
585 opac => { filesystem => getitemtypeimagedir('opac'),
586 url => getitemtypeimagesrc('opac'),
590 my @imagesets = (); # list of hasrefs of image set data to pass to template
591 my @subdirectories = _getSubdirectoryNames( $paths->{'staff'}{'filesystem'} );
593 foreach my $imagesubdir ( @subdirectories ) {
594 my @imagelist = (); # hashrefs of image info
595 my @imagenames = _getImagesFromDirectory( File::Spec->catfile( $paths->{'staff'}{'filesystem'}, $imagesubdir ) );
596 foreach my $thisimage ( @imagenames ) {
598 { KohaImage => "$imagesubdir/$thisimage",
599 StaffImageUrl => join( '/', $paths->{'staff'}{'url'}, $imagesubdir, $thisimage ),
600 OpacImageUrl => join( '/', $paths->{'opac'}{'url'}, $imagesubdir, $thisimage ),
601 checked => "$imagesubdir/$thisimage" eq $checked ? 1 : 0,
605 push @imagesets, { imagesetname => $imagesubdir,
606 images => \@imagelist };
614 $printers = &GetPrinters();
615 @queues = keys %$printers;
617 Returns information about existing printer queues.
619 C<$printers> is a reference-to-hash whose keys are the print queues
620 defined in the printers table of the Koha database. The values are
621 references-to-hash, whose keys are the fields in the printers table.
627 my $dbh = C4::Context->dbh;
628 my $sth = $dbh->prepare("select * from printers");
630 while ( my $printer = $sth->fetchrow_hashref ) {
631 $printers{ $printer->{'printqueue'} } = $printer;
633 return ( \%printers );
638 $printer = GetPrinter( $query, $printers );
642 sub GetPrinter ($$) {
643 my ( $query, $printers ) = @_; # get printer for this query from printers
644 my $printer = $query->param('printer');
645 my %cookie = $query->cookie('userenv');
646 ($printer) || ( $printer = $cookie{'printer'} ) || ( $printer = '' );
647 ( $printers->{$printer} ) || ( $printer = ( keys %$printers )[0] );
653 Returns the number of pages to display in a pagination bar, given the number
654 of items and the number of items per page.
659 my ( $nb_items, $nb_items_per_page ) = @_;
661 return int( ( $nb_items - 1 ) / $nb_items_per_page ) + 1;
666 (@themes) = &getallthemes('opac');
667 (@themes) = &getallthemes('intranet');
669 Returns an array of all available themes.
677 if ( $type eq 'intranet' ) {
678 $htdocs = C4::Context->config('intrahtdocs');
681 $htdocs = C4::Context->config('opachtdocs');
683 opendir D, "$htdocs";
684 my @dirlist = readdir D;
685 foreach my $directory (@dirlist) {
686 -d "$htdocs/$directory/en" and push @themes, $directory;
693 if ( C4::Context->preference("marcflavour") eq "UNIMARC" ) {
696 link_value => 'su-to',
697 label_value => 'Topics',
699 [ '600', '601', '602', '603', '604', '605', '606', '610' ],
703 link_value => 'su-geo',
704 label_value => 'Places',
709 link_value => 'su-ut',
710 label_value => 'Titles',
711 tags => [ '500', '501', '502', '503', '504', ],
716 label_value => 'Authors',
717 tags => [ '700', '701', '702', ],
722 label_value => 'Series',
731 link_value => 'branch',
732 label_value => 'Libraries',
737 push @$facets, $library_facet unless C4::Context->preference("singleBranchMode");
742 link_value => 'su-to',
743 label_value => 'Topics',
749 # link_value => 'su-na',
750 # label_value => 'People and Organizations',
751 # tags => ['600', '610', '611'],
755 link_value => 'su-geo',
756 label_value => 'Places',
761 link_value => 'su-ut',
762 label_value => 'Titles',
768 label_value => 'Authors',
769 tags => [ '100', '110', '700', ],
774 label_value => 'Series',
775 tags => [ '440', '490', ],
781 link_value => 'branch',
782 label_value => 'Libraries',
787 push @$facets, $library_facet unless C4::Context->preference("singleBranchMode");
794 Return a href where a key is associated to a href. You give a query,
795 the name of the key among the fields returned by the query. If you
796 also give as third argument the name of the value, the function
797 returns a href of scalar. The optional 4th argument is an arrayref of
798 items passed to the C<execute()> call. It is designed to bind
799 parameters to any placeholders in your SQL.
808 # generic href of any information on the item, href of href.
809 my $iteminfos_of = get_infos_of($query, 'itemnumber');
810 print $iteminfos_of->{$itemnumber}{barcode};
812 # specific information, href of scalar
813 my $barcode_of_item = get_infos_of($query, 'itemnumber', 'barcode');
814 print $barcode_of_item->{$itemnumber};
819 my ( $query, $key_name, $value_name, $bind_params ) = @_;
821 my $dbh = C4::Context->dbh;
823 my $sth = $dbh->prepare($query);
824 $sth->execute( @$bind_params );
827 while ( my $row = $sth->fetchrow_hashref ) {
828 if ( defined $value_name ) {
829 $infos_of{ $row->{$key_name} } = $row->{$value_name};
832 $infos_of{ $row->{$key_name} } = $row;
840 =head2 get_notforloan_label_of
842 my $notforloan_label_of = get_notforloan_label_of();
844 Each authorised value of notforloan (information available in items and
845 itemtypes) is link to a single label.
847 Returns a href where keys are authorised values and values are corresponding
850 foreach my $authorised_value (keys %{$notforloan_label_of}) {
852 "authorised_value: %s => %s\n",
854 $notforloan_label_of->{$authorised_value}
860 # FIXME - why not use GetAuthorisedValues ??
862 sub get_notforloan_label_of {
863 my $dbh = C4::Context->dbh;
866 SELECT authorised_value
867 FROM marc_subfield_structure
868 WHERE kohafield = \'items.notforloan\'
871 my $sth = $dbh->prepare($query);
873 my ($statuscode) = $sth->fetchrow_array();
878 FROM authorised_values
881 $sth = $dbh->prepare($query);
882 $sth->execute($statuscode);
883 my %notforloan_label_of;
884 while ( my $row = $sth->fetchrow_hashref ) {
885 $notforloan_label_of{ $row->{authorised_value} } = $row->{lib};
889 return \%notforloan_label_of;
892 =head2 displayServers
896 my $servers = displayServers();
898 my $servers = displayServers( $position );
900 my $servers = displayServers( $position, $type );
904 displayServers returns a listref of hashrefs, each containing
905 information about available z3950 servers. Each hashref has a format
909 'checked' => 'checked',
910 'encoding' => 'MARC-8'
912 'id' => 'LIBRARY OF CONGRESS',
916 'value' => 'z3950.loc.gov:7090/',
924 my ( $position, $type ) = @_;
925 my $dbh = C4::Context->dbh;
927 my $strsth = 'SELECT * FROM z3950servers';
932 push @bind_params, $position;
933 push @where_clauses, ' position = ? ';
937 push @bind_params, $type;
938 push @where_clauses, ' type = ? ';
941 # reassemble where clause from where clause pieces
942 if (@where_clauses) {
943 $strsth .= ' WHERE ' . join( ' AND ', @where_clauses );
946 my $rq = $dbh->prepare($strsth);
947 $rq->execute(@bind_params);
948 my @primaryserverloop;
950 while ( my $data = $rq->fetchrow_hashref ) {
951 push @primaryserverloop,
952 { label => $data->{description},
955 value => $data->{host} . ":" . $data->{port} . "/" . $data->{database},
956 encoding => ( $data->{encoding} ? $data->{encoding} : "iso-5426" ),
957 checked => "checked",
958 icon => $data->{icon},
959 zed => $data->{type} eq 'zed',
960 opensearch => $data->{type} eq 'opensearch'
963 return \@primaryserverloop;
966 sub displaySecondaryServers {
968 # my $secondary_servers_loop = [
969 # { inner_sup_servers_loop => [
970 # {label => "Google", id=>"GOOG", value=>"google",icon => "google.ico",opensearch => "1"},
971 # {label => "Yahoo", id=>"YAH", value=>"yahoo", icon =>"yahoo.ico", zed => "1"},
972 # {label => "Worldcat", id=>"WCT", value=>"worldcat", icon => "worldcat.gif", zed => "1"},
973 # {label => "Library of Congress", id=>"LOC", name=> "server", value=>"z3950.loc.gov:7090/Voyager", icon =>"loc.ico", zed => "1"},
977 return; #$secondary_servers_loop;
980 =head2 GetAuthValCode
982 $authvalcode = GetAuthValCode($kohafield,$frameworkcode);
987 my ($kohafield,$fwcode) = @_;
988 my $dbh = C4::Context->dbh;
989 $fwcode='' unless $fwcode;
990 my $sth = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield=? and frameworkcode=?');
991 $sth->execute($kohafield,$fwcode);
992 my ($authvalcode) = $sth->fetchrow_array;
996 =head2 GetAuthorisedValues
998 $authvalues = GetAuthorisedValues([$category], [$selected]);
1000 This function returns all authorised values from the'authosied_value' table in a reference to array of hashrefs.
1002 C<$category> returns authorised values for just one category (optional).
1006 sub GetAuthorisedValues {
1007 my ($category,$selected) = @_;
1009 my $dbh = C4::Context->dbh;
1010 my $query = "SELECT * FROM authorised_values";
1011 $query .= " WHERE category = '" . $category . "'" if $category;
1013 my $sth = $dbh->prepare($query);
1015 while (my $data=$sth->fetchrow_hashref) {
1016 if ($selected eq $data->{'authorised_value'} ) {
1017 $data->{'selected'} = 1;
1019 push @results, $data;
1021 #my $data = $sth->fetchall_arrayref({});
1022 return \@results; #$data;
1025 =head2 GetAuthorisedValueCategories
1027 $auth_categories = GetAuthorisedValueCategories();
1029 Return an arrayref of all of the available authorised
1034 sub GetAuthorisedValueCategories {
1035 my $dbh = C4::Context->dbh;
1036 my $sth = $dbh->prepare("SELECT DISTINCT category FROM authorised_values ORDER BY category");
1039 while (my $category = $sth->fetchrow_array) {
1040 push @results, $category;
1045 =head2 GetKohaAuthorisedValues
1047 Takes $kohafield, $fwcode as parameters.
1048 Returns hashref of Code => description
1050 if no authorised value category is defined for the kohafield.
1054 sub GetKohaAuthorisedValues {
1055 my ($kohafield,$fwcode,$codedvalue) = @_;
1056 $fwcode='' unless $fwcode;
1058 my $dbh = C4::Context->dbh;
1059 my $avcode = GetAuthValCode($kohafield,$fwcode);
1061 my $sth = $dbh->prepare("select authorised_value, lib from authorised_values where category=? ");
1062 $sth->execute($avcode);
1063 while ( my ($val, $lib) = $sth->fetchrow_array ) {
1064 $values{$val}= $lib;
1072 =head2 GetManagedTagSubfields
1076 $res = GetManagedTagSubfields();
1080 Returns a reference to a big hash of hash, with the Marc structure fro the given frameworkcode
1082 NOTE: This function is used only by the (incomplete) bulk editing feature. Since
1083 that feature currently does not deal with items and biblioitems changes
1084 correctly, those tags are specifically excluded from the list prepared
1087 For future reference, if a bulk item editing feature is implemented at some point, it
1088 needs some design thought -- for example, circulation status fields should not
1089 be changed willy-nilly.
1093 sub GetManagedTagSubfields{
1094 my $dbh=C4::Context->dbh;
1095 my $rq=$dbh->prepare(qq|
1097 DISTINCT CONCAT( marc_subfield_structure.tagfield, tagsubfield ) AS tagsubfield,
1098 marc_subfield_structure.liblibrarian as subfielddesc,
1099 marc_tag_structure.liblibrarian as tagdesc
1100 FROM marc_subfield_structure
1101 LEFT JOIN marc_tag_structure
1102 ON marc_tag_structure.tagfield = marc_subfield_structure.tagfield
1103 AND marc_tag_structure.frameworkcode = marc_subfield_structure.frameworkcode
1104 WHERE marc_subfield_structure.tab>=0
1105 AND marc_tag_structure.tagfield NOT IN (SELECT tagfield FROM marc_subfield_structure WHERE kohafield like 'items.%')
1106 AND marc_tag_structure.tagfield NOT IN (SELECT tagfield FROM marc_subfield_structure WHERE kohafield = 'biblioitems.itemtype')
1107 AND marc_subfield_structure.kohafield <> 'biblio.biblionumber'
1108 AND marc_subfield_structure.kohafield <> 'biblioitems.biblioitemnumber'
1109 ORDER BY marc_subfield_structure.tagfield, tagsubfield|);
1111 my $data=$rq->fetchall_arrayref({});
1115 =head2 display_marc_indicators
1119 # field is a MARC::Field object
1120 my $display_form = C4::Koha::display_marc_indicators($field);
1124 Generate a display form of the indicators of a variable
1125 MARC field, replacing any blanks with '#'.
1129 sub display_marc_indicators {
1131 my $indicators = '';
1132 if ($field->tag() >= 10) {
1133 $indicators = $field->indicator(1) . $field->indicator(2);
1134 $indicators =~ s/ /#/g;
1139 sub GetNormalizedUPC {
1140 my ($record,$marcflavour) = @_;
1143 if ($marcflavour eq 'MARC21') {
1144 @fields = $record->field('024');
1145 foreach my $field (@fields) {
1146 my $indicator = $field->indicator(1);
1147 my $upc = _normalize_match_point($field->subfield('a'));
1148 if ($indicator == 1 and $upc ne '') {
1153 else { # assume unimarc if not marc21
1154 @fields = $record->field('072');
1155 foreach my $field (@fields) {
1156 my $upc = _normalize_match_point($field->subfield('a'));
1164 # Normalizes and returns the first valid ISBN found in the record
1165 sub GetNormalizedISBN {
1166 my ($isbn,$record,$marcflavour) = @_;
1169 return _isbn_cleanup($isbn);
1171 return undef unless $record;
1173 if ($marcflavour eq 'MARC21') {
1174 @fields = $record->field('020');
1175 foreach my $field (@fields) {
1176 $isbn = $field->subfield('a');
1178 return _isbn_cleanup($isbn);
1184 else { # assume unimarc if not marc21
1185 @fields = $record->field('010');
1186 foreach my $field (@fields) {
1187 my $isbn = $field->subfield('a');
1189 return _isbn_cleanup($isbn);
1198 sub GetNormalizedEAN {
1199 my ($record,$marcflavour) = @_;
1202 if ($marcflavour eq 'MARC21') {
1203 @fields = $record->field('024');
1204 foreach my $field (@fields) {
1205 my $indicator = $field->indicator(1);
1206 $ean = _normalize_match_point($field->subfield('a'));
1207 if ($indicator == 3 and $ean ne '') {
1212 else { # assume unimarc if not marc21
1213 @fields = $record->field('073');
1214 foreach my $field (@fields) {
1215 $ean = _normalize_match_point($field->subfield('a'));
1222 sub GetNormalizedOCLCNumber {
1223 my ($record,$marcflavour) = @_;
1226 if ($marcflavour eq 'MARC21') {
1227 @fields = $record->field('035');
1228 foreach my $field (@fields) {
1229 $oclc = $field->subfield('a');
1230 if ($oclc =~ /OCoLC/) {
1231 $oclc =~ s/\(OCoLC\)//;
1238 else { # TODO: add UNIMARC fields
1242 sub _normalize_match_point {
1243 my $match_point = shift;
1244 (my $normalized_match_point) = $match_point =~ /([\d-]*[X]*)/;
1245 $normalized_match_point =~ s/-//g;
1247 return $normalized_match_point;
1250 sub _isbn_cleanup ($) {
1251 my $normalized_isbn = shift;
1252 $normalized_isbn =~/([0-9]{1,})/;
1253 $normalized_isbn = $1;
1255 $normalized_isbn =~ /\b(\d{13})\b/ or
1256 $normalized_isbn =~ /\b(\d{10})\b/ or
1257 $normalized_isbn =~ /\b(\d{9}X)\b/i