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 use vars qw($VERSION @ISA @EXPORT $DEBUG);
34 &subfield_is_koha_internal_p
35 &GetPrinters &GetPrinter
36 &GetItemTypes &getitemtypeinfo
39 &getframeworks &getframeworkinfo
40 &getauthtypes &getauthtype
45 &getitemtypeimagesrcfromurl
47 &get_notforloan_label_of
51 &GetAuthorisedValueCategories
52 &GetKohaAuthorisedValues
54 &GetManagedTagSubfields
63 C4::Koha - Perl Module containing convenience functions for Koha scripts
72 Koha.pm provides many functions for Koha scripts.
81 $slash_date = &slashifyDate($dash_date);
83 Takes a string of the form "DD-MM-YYYY" (or anything separated by
84 dashes), converts it to the form "YYYY/MM/DD", and returns the result.
90 # accepts a date of the form xx-xx-xx[xx] and returns it in the
92 my @dateOut = split( '-', shift );
93 return ("$dateOut[2]/$dateOut[1]/$dateOut[0]");
99 my $string = DisplayISBN( $isbn );
105 if (length ($isbn)<13){
107 if ( substr( $isbn, 0, 1 ) <= 7 ) {
108 $seg1 = substr( $isbn, 0, 1 );
110 elsif ( substr( $isbn, 0, 2 ) <= 94 ) {
111 $seg1 = substr( $isbn, 0, 2 );
113 elsif ( substr( $isbn, 0, 3 ) <= 995 ) {
114 $seg1 = substr( $isbn, 0, 3 );
116 elsif ( substr( $isbn, 0, 4 ) <= 9989 ) {
117 $seg1 = substr( $isbn, 0, 4 );
120 $seg1 = substr( $isbn, 0, 5 );
122 my $x = substr( $isbn, length($seg1) );
124 if ( substr( $x, 0, 2 ) <= 19 ) {
126 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
127 $seg2 = substr( $x, 0, 2 );
129 elsif ( substr( $x, 0, 3 ) <= 699 ) {
130 $seg2 = substr( $x, 0, 3 );
132 elsif ( substr( $x, 0, 4 ) <= 8399 ) {
133 $seg2 = substr( $x, 0, 4 );
135 elsif ( substr( $x, 0, 5 ) <= 89999 ) {
136 $seg2 = substr( $x, 0, 5 );
138 elsif ( substr( $x, 0, 6 ) <= 9499999 ) {
139 $seg2 = substr( $x, 0, 6 );
142 $seg2 = substr( $x, 0, 7 );
144 my $seg3 = substr( $x, length($seg2) );
145 $seg3 = substr( $seg3, 0, length($seg3) - 1 );
146 my $seg4 = substr( $x, -1, 1 );
147 return "$seg1-$seg2-$seg3-$seg4";
150 $seg1 = substr( $isbn, 0, 3 );
152 if ( substr( $isbn, 3, 1 ) <= 7 ) {
153 $seg2 = substr( $isbn, 3, 1 );
155 elsif ( substr( $isbn, 3, 2 ) <= 94 ) {
156 $seg2 = substr( $isbn, 3, 2 );
158 elsif ( substr( $isbn, 3, 3 ) <= 995 ) {
159 $seg2 = substr( $isbn, 3, 3 );
161 elsif ( substr( $isbn, 3, 4 ) <= 9989 ) {
162 $seg2 = substr( $isbn, 3, 4 );
165 $seg2 = substr( $isbn, 3, 5 );
167 my $x = substr( $isbn, length($seg2) +3);
169 if ( substr( $x, 0, 2 ) <= 19 ) {
171 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
172 $seg3 = substr( $x, 0, 2 );
174 elsif ( substr( $x, 0, 3 ) <= 699 ) {
175 $seg3 = substr( $x, 0, 3 );
177 elsif ( substr( $x, 0, 4 ) <= 8399 ) {
178 $seg3 = substr( $x, 0, 4 );
180 elsif ( substr( $x, 0, 5 ) <= 89999 ) {
181 $seg3 = substr( $x, 0, 5 );
183 elsif ( substr( $x, 0, 6 ) <= 9499999 ) {
184 $seg3 = substr( $x, 0, 6 );
187 $seg3 = substr( $x, 0, 7 );
189 my $seg4 = substr( $x, length($seg3) );
190 $seg4 = substr( $seg4, 0, length($seg4) - 1 );
191 my $seg5 = substr( $x, -1, 1 );
192 return "$seg1-$seg2-$seg3-$seg4-$seg5";
196 # FIXME.. this should be moved to a MARC-specific module
197 sub subfield_is_koha_internal_p ($) {
200 # We could match on 'lib' and 'tab' (and 'mandatory', & more to come!)
201 # But real MARC subfields are always single-character
202 # so it really is safer just to check the length
204 return length $subfield != 1;
209 $itemtypes = &GetItemTypes();
211 Returns information about existing itemtypes.
213 build a HTML select with the following code :
215 =head3 in PERL SCRIPT
217 my $itemtypes = GetItemTypes;
219 foreach my $thisitemtype (sort keys %$itemtypes) {
220 my $selected = 1 if $thisitemtype eq $itemtype;
221 my %row =(value => $thisitemtype,
222 selected => $selected,
223 description => $itemtypes->{$thisitemtype}->{'description'},
225 push @itemtypesloop, \%row;
227 $template->param(itemtypeloop => \@itemtypesloop);
231 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
232 <select name="itemtype">
233 <option value="">Default</option>
234 <!-- TMPL_LOOP name="itemtypeloop" -->
235 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="description" --></option>
238 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
239 <input type="submit" value="OK" class="button">
246 # returns a reference to a hash of references to branches...
248 my $dbh = C4::Context->dbh;
253 my $sth = $dbh->prepare($query);
255 while ( my $IT = $sth->fetchrow_hashref ) {
256 $itemtypes{ $IT->{'itemtype'} } = $IT;
258 return ( \%itemtypes );
261 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 $authtypes = &getauthtypes();
301 Returns information about existing authtypes.
303 build a HTML select with the following code :
305 =head3 in PERL SCRIPT
307 my $authtypes = getauthtypes;
309 foreach my $thisauthtype (keys %$authtypes) {
310 my $selected = 1 if $thisauthtype eq $authtype;
311 my %row =(value => $thisauthtype,
312 selected => $selected,
313 authtypetext => $authtypes->{$thisauthtype}->{'authtypetext'},
315 push @authtypesloop, \%row;
317 $template->param(itemtypeloop => \@itemtypesloop);
321 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
322 <select name="authtype">
323 <!-- TMPL_LOOP name="authtypeloop" -->
324 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="authtypetext" --></option>
327 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
328 <input type="submit" value="OK" class="button">
336 # returns a reference to a hash of references to authtypes...
338 my $dbh = C4::Context->dbh;
339 my $sth = $dbh->prepare("select * from auth_types order by authtypetext");
341 while ( my $IT = $sth->fetchrow_hashref ) {
342 $authtypes{ $IT->{'authtypecode'} } = $IT;
344 return ( \%authtypes );
348 my ($authtypecode) = @_;
350 # returns a reference to a hash of references to authtypes...
352 my $dbh = C4::Context->dbh;
353 my $sth = $dbh->prepare("select * from auth_types where authtypecode=?");
354 $sth->execute($authtypecode);
355 my $res = $sth->fetchrow_hashref;
361 $frameworks = &getframework();
363 Returns information about existing frameworks
365 build a HTML select with the following code :
367 =head3 in PERL SCRIPT
369 my $frameworks = frameworks();
371 foreach my $thisframework (keys %$frameworks) {
372 my $selected = 1 if $thisframework eq $frameworkcode;
373 my %row =(value => $thisframework,
374 selected => $selected,
375 description => $frameworks->{$thisframework}->{'frameworktext'},
377 push @frameworksloop, \%row;
379 $template->param(frameworkloop => \@frameworksloop);
383 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
384 <select name="frameworkcode">
385 <option value="">Default</option>
386 <!-- TMPL_LOOP name="frameworkloop" -->
387 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="frameworktext" --></option>
390 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
391 <input type="submit" value="OK" class="button">
399 # returns a reference to a hash of references to branches...
401 my $dbh = C4::Context->dbh;
402 my $sth = $dbh->prepare("select * from biblio_framework");
404 while ( my $IT = $sth->fetchrow_hashref ) {
405 $itemtypes{ $IT->{'frameworkcode'} } = $IT;
407 return ( \%itemtypes );
410 =head2 getframeworkinfo
412 $frameworkinfo = &getframeworkinfo($frameworkcode);
414 Returns information about an frameworkcode.
418 sub getframeworkinfo {
419 my ($frameworkcode) = @_;
420 my $dbh = C4::Context->dbh;
422 $dbh->prepare("select * from biblio_framework where frameworkcode=?");
423 $sth->execute($frameworkcode);
424 my $res = $sth->fetchrow_hashref;
428 =head2 getitemtypeinfo
430 $itemtype = &getitemtype($itemtype);
432 Returns information about an itemtype.
436 sub getitemtypeinfo {
438 my $dbh = C4::Context->dbh;
439 my $sth = $dbh->prepare("select * from itemtypes where itemtype=?");
440 $sth->execute($itemtype);
441 my $res = $sth->fetchrow_hashref;
443 $res->{imageurl} = getitemtypeimagesrcfromurl( $res->{imageurl} );
448 sub getitemtypeimagesrcfromurl {
451 if ( defined $imageurl and $imageurl !~ m/^http/ ) {
452 $imageurl = getitemtypeimagesrc() . '/' . $imageurl;
458 =head2 getitemtypeimagedir
464 my $directory = getitemtypeimagedir( 'opac' );
466 pass in 'opac' or 'intranet'. Defaults to 'opac'.
468 returns the full path to the appropriate directory containing images.
474 sub getitemtypeimagedir {
476 $src = 'opac' unless defined $src;
478 if ($src eq 'intranet') {
479 return C4::Context->config('intrahtdocs') . '/' .C4::Context->preference('template') . '/img/itemtypeimg';
482 return C4::Context->config('opachtdocs') . '/' . C4::Context->preference('template') . '/itemtypeimg';
486 sub getitemtypeimagesrc {
488 if ($src eq 'intranet') {
489 return '/intranet-tmpl' . '/' . C4::Context->preference('template') . '/img/itemtypeimg';
492 return '/opac-tmpl' . '/' . C4::Context->preference('template') . '/itemtypeimg';
496 =head3 _getImagesFromDirectory
498 Find all of the image files in a directory in the filesystem
503 returns: a list of images in that directory.
505 Notes: this does not traverse into subdirectories. See
506 _getSubdirectoryNames for help with that.
507 Images are assumed to be files with .gif or .png file extensions.
508 The image names returned do not have the directory name on them.
512 sub _getImagesFromDirectory {
513 my $directoryname = shift;
514 return unless defined $directoryname;
515 return unless -d $directoryname;
517 if ( opendir ( my $dh, $directoryname ) ) {
518 my @images = grep { /\.(gif|png)$/i } readdir( $dh );
522 warn "unable to opendir $directoryname: $!";
527 =head3 _getSubdirectoryNames
529 Find all of the directories in a directory in the filesystem
534 returns: a list of subdirectories in that directory.
536 Notes: this does not traverse into subdirectories. Only the first
537 level of subdirectories are returned.
538 The directory names returned don't have the parent directory name
543 sub _getSubdirectoryNames {
544 my $directoryname = shift;
545 return unless defined $directoryname;
546 return unless -d $directoryname;
548 if ( opendir ( my $dh, $directoryname ) ) {
549 my @directories = grep { -d File::Spec->catfile( $directoryname, $_ ) && ! ( /^\./ ) } readdir( $dh );
553 warn "unable to opendir $directoryname: $!";
560 returns: a listref of hashrefs. Each hash represents another collection of images.
561 { imagesetname => 'npl', # the name of the image set (npl is the original one)
562 images => listref of image hashrefs
565 each image is represented by a hashref like this:
566 { KohaImage => 'npl/image.gif',
567 StaffImageUrl => '/intranet-tmpl/prog/img/itemtypeimg/npl/image.gif',
568 OpacImageURL => '/opac-tmpl/prog/itemtypeimg/npl/image.gif'
569 checked => 0 or 1: was this the image passed to this method?
570 Note: I'd like to remove this somehow.
577 my $checked = $params{'checked'} || '';
579 my $paths = { staff => { filesystem => getitemtypeimagedir('intranet'),
580 url => getitemtypeimagesrc('intranet'),
582 opac => { filesystem => getitemtypeimagedir('opac'),
583 url => getitemtypeimagesrc('opac'),
587 my @imagesets = (); # list of hasrefs of image set data to pass to template
588 my @subdirectories = _getSubdirectoryNames( $paths->{'staff'}{'filesystem'} );
590 foreach my $imagesubdir ( @subdirectories ) {
591 my @imagelist = (); # hashrefs of image info
592 my @imagenames = _getImagesFromDirectory( File::Spec->catfile( $paths->{'staff'}{'filesystem'}, $imagesubdir ) );
593 foreach my $thisimage ( @imagenames ) {
595 { KohaImage => "$imagesubdir/$thisimage",
596 StaffImageUrl => join( '/', $paths->{'staff'}{'url'}, $imagesubdir, $thisimage ),
597 OpacImageUrl => join( '/', $paths->{'opac'}{'url'}, $imagesubdir, $thisimage ),
598 checked => "$imagesubdir/$thisimage" eq $checked ? 1 : 0,
602 push @imagesets, { imagesetname => $imagesubdir,
603 images => \@imagelist };
611 $printers = &GetPrinters();
612 @queues = keys %$printers;
614 Returns information about existing printer queues.
616 C<$printers> is a reference-to-hash whose keys are the print queues
617 defined in the printers table of the Koha database. The values are
618 references-to-hash, whose keys are the fields in the printers table.
624 my $dbh = C4::Context->dbh;
625 my $sth = $dbh->prepare("select * from printers");
627 while ( my $printer = $sth->fetchrow_hashref ) {
628 $printers{ $printer->{'printqueue'} } = $printer;
630 return ( \%printers );
635 $printer = GetPrinter( $query, $printers );
639 sub GetPrinter ($$) {
640 my ( $query, $printers ) = @_; # get printer for this query from printers
641 my $printer = $query->param('printer');
642 my %cookie = $query->cookie('userenv');
643 ($printer) || ( $printer = $cookie{'printer'} ) || ( $printer = '' );
644 ( $printers->{$printer} ) || ( $printer = ( keys %$printers )[0] );
650 Returns the number of pages to display in a pagination bar, given the number
651 of items and the number of items per page.
656 my ( $nb_items, $nb_items_per_page ) = @_;
658 return int( ( $nb_items - 1 ) / $nb_items_per_page ) + 1;
663 (@themes) = &getallthemes('opac');
664 (@themes) = &getallthemes('intranet');
666 Returns an array of all available themes.
674 if ( $type eq 'intranet' ) {
675 $htdocs = C4::Context->config('intrahtdocs');
678 $htdocs = C4::Context->config('opachtdocs');
680 opendir D, "$htdocs";
681 my @dirlist = readdir D;
682 foreach my $directory (@dirlist) {
683 -d "$htdocs/$directory/en" and push @themes, $directory;
690 if ( C4::Context->preference("marcflavour") eq "UNIMARC" ) {
693 link_value => 'su-to',
694 label_value => 'Topics',
696 [ '600', '601', '602', '603', '604', '605', '606', '610' ],
700 link_value => 'su-geo',
701 label_value => 'Places',
706 link_value => 'su-ut',
707 label_value => 'Titles',
708 tags => [ '500', '501', '502', '503', '504', ],
713 label_value => 'Authors',
714 tags => [ '700', '701', '702', ],
719 label_value => 'Series',
728 link_value => 'branch',
729 label_value => 'Libraries',
734 push @$facets, $library_facet unless C4::Context->preference("singleBranchMode");
739 link_value => 'su-to',
740 label_value => 'Topics',
746 # link_value => 'su-na',
747 # label_value => 'People and Organizations',
748 # tags => ['600', '610', '611'],
752 link_value => 'su-geo',
753 label_value => 'Places',
758 link_value => 'su-ut',
759 label_value => 'Titles',
765 label_value => 'Authors',
766 tags => [ '100', '110', '700', ],
771 label_value => 'Series',
772 tags => [ '440', '490', ],
778 link_value => 'branch',
779 label_value => 'Libraries',
784 push @$facets, $library_facet unless C4::Context->preference("singleBranchMode");
791 Return a href where a key is associated to a href. You give a query, the
792 name of the key among the fields returned by the query. If you also give as
793 third argument the name of the value, the function returns a href of scalar.
802 # generic href of any information on the item, href of href.
803 my $iteminfos_of = get_infos_of($query, 'itemnumber');
804 print $iteminfos_of->{$itemnumber}{barcode};
806 # specific information, href of scalar
807 my $barcode_of_item = get_infos_of($query, 'itemnumber', 'barcode');
808 print $barcode_of_item->{$itemnumber};
813 my ( $query, $key_name, $value_name ) = @_;
815 my $dbh = C4::Context->dbh;
817 my $sth = $dbh->prepare($query);
821 while ( my $row = $sth->fetchrow_hashref ) {
822 if ( defined $value_name ) {
823 $infos_of{ $row->{$key_name} } = $row->{$value_name};
826 $infos_of{ $row->{$key_name} } = $row;
834 =head2 get_notforloan_label_of
836 my $notforloan_label_of = get_notforloan_label_of();
838 Each authorised value of notforloan (information available in items and
839 itemtypes) is link to a single label.
841 Returns a href where keys are authorised values and values are corresponding
844 foreach my $authorised_value (keys %{$notforloan_label_of}) {
846 "authorised_value: %s => %s\n",
848 $notforloan_label_of->{$authorised_value}
854 # FIXME - why not use GetAuthorisedValues ??
856 sub get_notforloan_label_of {
857 my $dbh = C4::Context->dbh;
860 SELECT authorised_value
861 FROM marc_subfield_structure
862 WHERE kohafield = \'items.notforloan\'
865 my $sth = $dbh->prepare($query);
867 my ($statuscode) = $sth->fetchrow_array();
872 FROM authorised_values
875 $sth = $dbh->prepare($query);
876 $sth->execute($statuscode);
877 my %notforloan_label_of;
878 while ( my $row = $sth->fetchrow_hashref ) {
879 $notforloan_label_of{ $row->{authorised_value} } = $row->{lib};
883 return \%notforloan_label_of;
887 my ( $position, $type ) = @_;
888 my $dbh = C4::Context->dbh;
889 my $strsth = "SELECT * FROM z3950servers where 1";
890 $strsth .= " AND position=\"$position\"" if ($position);
891 $strsth .= " AND type=\"$type\"" if ($type);
892 my $rq = $dbh->prepare($strsth);
894 my @primaryserverloop;
896 while ( my $data = $rq->fetchrow_hashref ) {
898 $cell{label} = $data->{'description'};
899 $cell{id} = $data->{'name'};
902 . ( $data->{port} ? ":" . $data->{port} : "" ) . "/"
904 if ( $data->{host} );
905 $cell{checked} = $data->{checked};
906 push @primaryserverloop,
908 label => $data->{description},
911 value => $data->{host} . ":"
912 . $data->{port} . "/"
914 encoding => ($data->{encoding}?$data->{encoding}:"iso-5426"),
915 checked => "checked",
916 icon => $data->{icon},
917 zed => $data->{type} eq 'zed',
918 opensearch => $data->{type} eq 'opensearch'
921 return \@primaryserverloop;
924 sub displaySecondaryServers {
926 # my $secondary_servers_loop = [
927 # { inner_sup_servers_loop => [
928 # {label => "Google", id=>"GOOG", value=>"google",icon => "google.ico",opensearch => "1"},
929 # {label => "Yahoo", id=>"YAH", value=>"yahoo", icon =>"yahoo.ico", zed => "1"},
930 # {label => "Worldcat", id=>"WCT", value=>"worldcat", icon => "worldcat.gif", zed => "1"},
931 # {label => "Library of Congress", id=>"LOC", name=> "server", value=>"z3950.loc.gov:7090/Voyager", icon =>"loc.ico", zed => "1"},
935 return; #$secondary_servers_loop;
938 =head2 GetAuthValCode
940 $authvalcode = GetAuthValCode($kohafield,$frameworkcode);
945 my ($kohafield,$fwcode) = @_;
946 my $dbh = C4::Context->dbh;
947 $fwcode='' unless $fwcode;
948 my $sth = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield=? and frameworkcode=?');
949 $sth->execute($kohafield,$fwcode);
950 my ($authvalcode) = $sth->fetchrow_array;
954 =head2 GetAuthorisedValues
956 $authvalues = GetAuthorisedValues($category);
958 this function get all authorised values from 'authosied_value' table into a reference to array which
959 each value containt an hashref.
961 Set C<$category> on input args if you want to limits your query to this one. This params is not mandatory.
965 sub GetAuthorisedValues {
966 my ($category,$selected) = @_;
969 my $dbh = C4::Context->dbh;
970 my $query = "SELECT * FROM authorised_values";
971 $query .= " WHERE category = '" . $category . "'" if $category;
973 my $sth = $dbh->prepare($query);
975 while (my $data=$sth->fetchrow_hashref) {
976 if ($selected eq $data->{'authorised_value'} ) {
977 $data->{'selected'} = 1;
979 $results[$count] = $data;
982 #my $data = $sth->fetchall_arrayref({});
983 return \@results; #$data;
986 =head2 GetAuthorisedValueCategories
988 $auth_categories = GetAuthorisedValueCategories();
990 Return an arrayref of all of the available authorised
995 sub GetAuthorisedValueCategories {
996 my $dbh = C4::Context->dbh;
997 my $sth = $dbh->prepare("SELECT DISTINCT category FROM authorised_values ORDER BY category");
1000 while (my $category = $sth->fetchrow_array) {
1001 push @results, $category;
1006 =head2 GetKohaAuthorisedValues
1008 Takes $kohafield, $fwcode as parameters.
1009 Returns hashref of Code => description
1011 if no authorised value category is defined for the kohafield.
1015 sub GetKohaAuthorisedValues {
1016 my ($kohafield,$fwcode,$codedvalue) = @_;
1017 $fwcode='' unless $fwcode;
1019 my $dbh = C4::Context->dbh;
1020 my $avcode = GetAuthValCode($kohafield,$fwcode);
1022 my $sth = $dbh->prepare("select authorised_value, lib from authorised_values where category=? ");
1023 $sth->execute($avcode);
1024 while ( my ($val, $lib) = $sth->fetchrow_array ) {
1025 $values{$val}= $lib;
1033 =head2 GetManagedTagSubfields
1037 $res = GetManagedTagSubfields();
1041 Returns a reference to a big hash of hash, with the Marc structure fro the given frameworkcode
1043 NOTE: This function is used only by the (incomplete) bulk editing feature. Since
1044 that feature currently does not deal with items and biblioitems changes
1045 correctly, those tags are specifically excluded from the list prepared
1048 For future reference, if a bulk item editing feature is implemented at some point, it
1049 needs some design thought -- for example, circulation status fields should not
1050 be changed willy-nilly.
1054 sub GetManagedTagSubfields{
1055 my $dbh=C4::Context->dbh;
1056 my $rq=$dbh->prepare(qq|
1058 DISTINCT CONCAT( marc_subfield_structure.tagfield, tagsubfield ) AS tagsubfield,
1059 marc_subfield_structure.liblibrarian as subfielddesc,
1060 marc_tag_structure.liblibrarian as tagdesc
1061 FROM marc_subfield_structure
1062 LEFT JOIN marc_tag_structure
1063 ON marc_tag_structure.tagfield = marc_subfield_structure.tagfield
1064 AND marc_tag_structure.frameworkcode = marc_subfield_structure.frameworkcode
1065 WHERE marc_subfield_structure.tab>=0
1066 AND marc_tag_structure.tagfield NOT IN (SELECT tagfield FROM marc_subfield_structure WHERE kohafield like 'items.%')
1067 AND marc_tag_structure.tagfield NOT IN (SELECT tagfield FROM marc_subfield_structure WHERE kohafield = 'biblioitems.itemtype')
1068 AND marc_subfield_structure.kohafield <> 'biblio.biblionumber'
1069 AND marc_subfield_structure.kohafield <> 'biblioitems.biblioitemnumber'
1070 ORDER BY marc_subfield_structure.tagfield, tagsubfield|);
1072 my $data=$rq->fetchall_arrayref({});
1076 =head2 display_marc_indicators
1080 # field is a MARC::Field object
1081 my $display_form = C4::Koha::display_marc_indicators($field);
1085 Generate a display form of the indicators of a variable
1086 MARC field, replacing any blanks with '#'.
1090 sub display_marc_indicators {
1092 my $indicators = '';
1093 if ($field->tag() >= 10) {
1094 $indicators = $field->indicator(1) . $field->indicator(2);
1095 $indicators =~ s/ /#/g;