3 # Copyright 2000-2002 Katipo Communications
4 # Parts Copyright 2010 Nelsonville Public Library
5 # Parts copyright 2010 BibLibre
7 # This file is part of Koha.
9 # Koha is free software; you can redistribute it and/or modify it under the
10 # terms of the GNU General Public License as published by the Free Software
11 # Foundation; either version 2 of the License, or (at your option) any later
14 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
15 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License along
19 # with Koha; if not, write to the Free Software Foundation, Inc.,
20 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #use warnings; FIXME - Bug 2505
27 use C4
::Branch
qw(GetBranchesCount);
30 use DateTime
::Format
::MySQL
;
31 use autouse
'Data::Dumper' => qw(Dumper);
33 use vars
qw($VERSION @ISA @EXPORT @EXPORT_OK $DEBUG);
36 $VERSION = 3.07.00.049;
41 &subfield_is_koha_internal_p
42 &GetPrinters &GetPrinter
43 &GetItemTypes &getitemtypeinfo
45 &GetSupportName &GetSupportList
47 &getframeworks &getframeworkinfo
48 &getauthtypes &getauthtype
54 &get_notforloan_label_of
57 &getitemtypeimagelocation
59 &GetAuthorisedValueCategories
60 &GetKohaAuthorisedValues
61 &GetKohaAuthorisedValuesFromField
62 &GetKohaAuthorisedValueLib
63 &GetAuthorisedValueByCode
64 &GetKohaImageurlFromAuthorisedValues
70 &GetNormalizedOCLCNumber
76 @EXPORT_OK = qw( GetDailyQuote );
80 memoize
('GetAuthorisedValues');
84 C4::Koha - Perl Module containing convenience functions for Koha scripts
92 Koha.pm provides many functions for Koha scripts.
100 $slash_date = &slashifyDate($dash_date);
102 Takes a string of the form "DD-MM-YYYY" (or anything separated by
103 dashes), converts it to the form "YYYY/MM/DD", and returns the result.
109 # accepts a date of the form xx-xx-xx[xx] and returns it in the
111 my @dateOut = split( '-', shift );
112 return ("$dateOut[2]/$dateOut[1]/$dateOut[0]");
115 # FIXME.. this should be moved to a MARC-specific module
116 sub subfield_is_koha_internal_p
{
119 # We could match on 'lib' and 'tab' (and 'mandatory', & more to come!)
120 # But real MARC subfields are always single-character
121 # so it really is safer just to check the length
123 return length $subfield != 1;
126 =head2 GetSupportName
128 $itemtypename = &GetSupportName($codestring);
130 Returns a string with the name of the itemtype.
136 return if (! $codestring);
138 my $advanced_search_types = C4
::Context
->preference("AdvancedSearchTypes");
139 if (!$advanced_search_types or $advanced_search_types eq 'itemtypes') {
146 my $sth = C4
::Context
->dbh->prepare($query);
147 $sth->execute($codestring);
148 ($resultstring)=$sth->fetchrow;
149 return $resultstring;
152 C4
::Context
->dbh->prepare(
153 "SELECT lib FROM authorised_values WHERE category = ? AND authorised_value = ?"
155 $sth->execute( $advanced_search_types, $codestring );
156 my $data = $sth->fetchrow_hashref;
157 return $$data{'lib'};
161 =head2 GetSupportList
163 $itemtypes = &GetSupportList();
165 Returns an array ref containing informations about Support (since itemtype is rather a circulation code when item-level-itypes is used).
167 build a HTML select with the following code :
169 =head3 in PERL SCRIPT
171 my $itemtypes = GetSupportList();
172 $template->param(itemtypeloop => $itemtypes);
176 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
177 <select name="itemtype">
178 <option value="">Default</option>
179 <!-- TMPL_LOOP name="itemtypeloop" -->
180 <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>
183 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
184 <input type="submit" value="OK" class="button">
190 my $advanced_search_types = C4
::Context
->preference("AdvancedSearchTypes");
191 if (!$advanced_search_types or $advanced_search_types eq 'itemtypes') {
197 my $sth = C4
::Context
->dbh->prepare($query);
199 return $sth->fetchall_arrayref({});
201 my $advsearchtypes = GetAuthorisedValues
($advanced_search_types);
202 my @results= map {{itemtype
=>$$_{authorised_value
},description
=>$$_{lib
},imageurl
=>$$_{imageurl
}}} @
$advsearchtypes;
208 $itemtypes = &GetItemTypes();
210 Returns information about existing itemtypes.
212 build a HTML select with the following code :
214 =head3 in PERL SCRIPT
216 my $itemtypes = GetItemTypes;
218 foreach my $thisitemtype (sort keys %$itemtypes) {
219 my $selected = 1 if $thisitemtype eq $itemtype;
220 my %row =(value => $thisitemtype,
221 selected => $selected,
222 description => $itemtypes->{$thisitemtype}->{'description'},
224 push @itemtypesloop, \%row;
226 $template->param(itemtypeloop => \@itemtypesloop);
230 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
231 <select name="itemtype">
232 <option value="">Default</option>
233 <!-- TMPL_LOOP name="itemtypeloop" -->
234 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="description" --></option>
237 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
238 <input type="submit" value="OK" class="button">
245 # returns a reference to a hash of references to itemtypes...
247 my $dbh = C4
::Context
->dbh;
252 my $sth = $dbh->prepare($query);
254 while ( my $IT = $sth->fetchrow_hashref ) {
255 $itemtypes{ $IT->{'itemtype'} } = $IT;
257 return ( \
%itemtypes );
260 sub get_itemtypeinfos_of
{
263 my $placeholders = join( ', ', map { '?' } @itemtypes );
264 my $query = <<"END_SQL";
270 WHERE itemtype IN ( $placeholders )
273 return get_infos_of( $query, 'itemtype', undef, \@itemtypes );
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">
398 # returns a reference to a hash of references to branches...
400 my $dbh = C4::Context->dbh;
401 my $sth = $dbh->prepare("select * from biblio_framework");
403 while ( my $IT = $sth->fetchrow_hashref ) {
404 $itemtypes{ $IT->{'frameworkcode'} } = $IT;
406 return ( \%itemtypes );
409 =head2 getframeworkinfo
411 $frameworkinfo = &getframeworkinfo($frameworkcode);
413 Returns information about an frameworkcode.
417 sub getframeworkinfo {
418 my ($frameworkcode) = @_;
419 my $dbh = C4::Context->dbh;
421 $dbh->prepare("select * from biblio_framework where frameworkcode=?");
422 $sth->execute($frameworkcode);
423 my $res = $sth->fetchrow_hashref;
427 =head2 getitemtypeinfo
429 $itemtype = &getitemtypeinfo($itemtype, [$interface]);
431 Returns information about an itemtype. The optional $interface argument
432 sets which interface ('opac' or 'intranet') to return the imageurl for.
433 Defaults to intranet.
437 sub getitemtypeinfo {
438 my ($itemtype, $interface) = @_;
439 my $dbh = C4::Context->dbh;
440 my $sth = $dbh->prepare("select * from itemtypes where itemtype=?");
441 $sth->execute($itemtype);
442 my $res = $sth->fetchrow_hashref;
444 $res->{imageurl} = getitemtypeimagelocation( ( ( defined $interface && $interface eq 'opac' ) ? 'opac' : 'intranet' ), $res->{imageurl} );
449 =head2 getitemtypeimagedir
451 my $directory = getitemtypeimagedir( 'opac' );
453 pass in 'opac' or 'intranet'. Defaults to 'opac'.
455 returns the full path to the appropriate directory containing images.
459 sub getitemtypeimagedir {
460 my $src = shift || 'opac';
461 if ($src eq 'intranet') {
462 return C4::Context->config('intrahtdocs') . '/' .C4::Context->preference('template') . '/img/itemtypeimg';
464 return C4::Context->config('opachtdocs') . '/' . C4::Context->preference('opacthemes') . '/itemtypeimg';
468 sub getitemtypeimagesrc {
469 my $src = shift || 'opac';
470 if ($src eq 'intranet') {
471 return '/intranet-tmpl' . '/' . C4::Context->preference('template') . '/img/itemtypeimg';
473 return '/opac-tmpl' . '/' . C4::Context->preference('opacthemes') . '/itemtypeimg';
477 sub getitemtypeimagelocation {
478 my ( $src, $image ) = @_;
480 return '' if ( !$image );
483 my $scheme = ( URI::Split::uri_split( $image ) )[0];
485 return $image if ( $scheme );
487 return getitemtypeimagesrc( $src ) . '/' . $image;
490 =head3 _getImagesFromDirectory
492 Find all of the image files in a directory in the filesystem
494 parameters: a directory name
496 returns: a list of images in that directory.
498 Notes: this does not traverse into subdirectories. See
499 _getSubdirectoryNames for help with that.
500 Images are assumed to be files with .gif or .png file extensions.
501 The image names returned do not have the directory name on them.
505 sub _getImagesFromDirectory {
506 my $directoryname = shift;
507 return unless defined $directoryname;
508 return unless -d $directoryname;
510 if ( opendir ( my $dh, $directoryname ) ) {
511 my @images = grep { /\.(gif|png)$/i } readdir( $dh );
513 @images = sort(@images);
516 warn "unable to opendir $directoryname: $!";
521 =head3 _getSubdirectoryNames
523 Find all of the directories in a directory in the filesystem
525 parameters: a directory name
527 returns: a list of subdirectories in that directory.
529 Notes: this does not traverse into subdirectories. Only the first
530 level of subdirectories are returned.
531 The directory names returned don't have the parent directory name on them.
535 sub _getSubdirectoryNames {
536 my $directoryname = shift;
537 return unless defined $directoryname;
538 return unless -d $directoryname;
540 if ( opendir ( my $dh, $directoryname ) ) {
541 my @directories = grep { -d File::Spec->catfile( $directoryname, $_ ) && ! ( /^\./ ) } readdir( $dh );
545 warn "unable to opendir $directoryname: $!";
552 returns: a listref of hashrefs. Each hash represents another collection of images.
554 { imagesetname => 'npl', # the name of the image set (npl is the original one)
555 images => listref of image hashrefs
558 each image is represented by a hashref like this:
560 { KohaImage => 'npl/image.gif',
561 StaffImageUrl => '/intranet-tmpl/prog/img/itemtypeimg/npl/image.gif',
562 OpacImageURL => '/opac-tmpl/prog/itemtypeimg/npl/image.gif'
563 checked => 0 or 1: was this the image passed to this method?
564 Note: I'd like to remove this somehow.
571 my $checked = $params{'checked'} || '';
573 my $paths = { staff => { filesystem => getitemtypeimagedir('intranet'),
574 url => getitemtypeimagesrc('intranet'),
576 opac => { filesystem => getitemtypeimagedir('opac'),
577 url => getitemtypeimagesrc('opac'),
581 my @imagesets = (); # list of hasrefs of image set data to pass to template
582 my @subdirectories = _getSubdirectoryNames( $paths->{'staff'}{'filesystem'} );
583 foreach my $imagesubdir ( @subdirectories ) {
584 warn $imagesubdir if $DEBUG;
585 my @imagelist = (); # hashrefs of image info
586 my @imagenames = _getImagesFromDirectory( File::Spec->catfile( $paths->{'staff'}{'filesystem'}, $imagesubdir ) );
587 my $imagesetactive = 0;
588 foreach my $thisimage ( @imagenames ) {
590 { KohaImage => "$imagesubdir/$thisimage",
591 StaffImageUrl => join( '/', $paths->{'staff'}{'url'}, $imagesubdir, $thisimage ),
592 OpacImageUrl => join( '/', $paths->{'opac'}{'url'}, $imagesubdir, $thisimage ),
593 checked => "$imagesubdir/$thisimage" eq $checked ? 1 : 0,
596 $imagesetactive = 1 if "$imagesubdir/$thisimage" eq $checked;
598 push @imagesets, { imagesetname => $imagesubdir,
599 imagesetactive => $imagesetactive,
600 images => \@imagelist };
608 $printers = &GetPrinters();
609 @queues = keys %$printers;
611 Returns information about existing printer queues.
613 C<$printers> is a reference-to-hash whose keys are the print queues
614 defined in the printers table of the Koha database. The values are
615 references-to-hash, whose keys are the fields in the printers table.
621 my $dbh = C4::Context->dbh;
622 my $sth = $dbh->prepare("select * from printers");
624 while ( my $printer = $sth->fetchrow_hashref ) {
625 $printers{ $printer->{'printqueue'} } = $printer;
627 return ( \%printers );
632 $printer = GetPrinter( $query, $printers );
637 my ( $query, $printers ) = @_; # get printer for this query from printers
638 my $printer = $query->param('printer');
639 my %cookie = $query->cookie('userenv');
640 ($printer) || ( $printer = $cookie{'printer'} ) || ( $printer = '' );
641 ( $printers->{$printer} ) || ( $printer = ( keys %$printers )[0] );
647 Returns the number of pages to display in a pagination bar, given the number
648 of items and the number of items per page.
653 my ( $nb_items, $nb_items_per_page ) = @_;
655 return int( ( $nb_items - 1 ) / $nb_items_per_page ) + 1;
660 (@themes) = &getallthemes('opac');
661 (@themes) = &getallthemes('intranet');
663 Returns an array of all available themes.
671 if ( $type eq 'intranet' ) {
672 $htdocs = C4::Context->config('intrahtdocs');
675 $htdocs = C4::Context->config('opachtdocs');
677 opendir D, "$htdocs";
678 my @dirlist = readdir D;
679 foreach my $directory (@dirlist) {
680 next if $directory eq 'lib';
681 -d "$htdocs/$directory/en" and push @themes, $directory;
688 if ( C4::Context->preference("marcflavour") eq "UNIMARC" ) {
693 tags => [ qw/ 600ab 601ab 602a 604at 605a 606ax 610a / ],
699 tags => [ qw/ 607a / ],
705 tags => [ qw/ 500a 501a 503a / ],
711 tags => [ qw/ 700ab 701ab 702ab / ],
712 sep => C4::Context->preference("UNIMARCAuthorsFacetsSeparator"),
717 tags => [ qw/ 225a / ],
723 unless ( C4::Context->preference("singleBranchMode") || GetBranchesCount() == 1 ) {
726 label => 'Libraries',
727 tags => [ qw/ 995b / ],
733 tags => [ qw/ 995c / ],
736 push( @$facets, $library_facet );
743 tags => [ qw/ 650a / ],
748 # label => 'People and Organizations',
749 # tags => [ qw/ 600a 610a 611a / ],
755 tags => [ qw/ 651a / ],
761 tags => [ qw/ 630a / ],
767 tags => [ qw/ 100a 110a 700a / ],
773 tags => [ qw/ 440a 490a / ],
778 label => 'ItemTypes',
779 tags => [ qw/ 952y 942c / ],
785 unless ( C4::Context->preference("singleBranchMode") || GetBranchesCount() == 1 ) {
788 label => 'Libraries',
789 tags => [ qw / 952b / ],
795 tags => [ qw / 952c / ],
798 push( @$facets, $library_facet );
805 Return a href where a key is associated to a href. You give a query,
806 the name of the key among the fields returned by the query. If you
807 also give as third argument the name of the value, the function
808 returns a href of scalar. The optional 4th argument is an arrayref of
809 items passed to the C<execute()> call. It is designed to bind
810 parameters to any placeholders in your SQL.
819 # generic href of any information on the item, href of href.
820 my $iteminfos_of = get_infos_of($query, 'itemnumber');
821 print $iteminfos_of->{$itemnumber}{barcode};
823 # specific information, href of scalar
824 my $barcode_of_item = get_infos_of($query, 'itemnumber', 'barcode');
825 print $barcode_of_item->{$itemnumber};
830 my ( $query, $key_name, $value_name, $bind_params ) = @_;
832 my $dbh = C4::Context->dbh;
834 my $sth = $dbh->prepare($query);
835 $sth->execute( @$bind_params );
838 while ( my $row = $sth->fetchrow_hashref ) {
839 if ( defined $value_name ) {
840 $infos_of{ $row->{$key_name} } = $row->{$value_name};
843 $infos_of{ $row->{$key_name} } = $row;
851 =head2 get_notforloan_label_of
853 my $notforloan_label_of = get_notforloan_label_of();
855 Each authorised value of notforloan (information available in items and
856 itemtypes) is link to a single label.
858 Returns a href where keys are authorised values and values are corresponding
861 foreach my $authorised_value (keys %{$notforloan_label_of}) {
863 "authorised_value: %s => %s\n",
865 $notforloan_label_of->{$authorised_value}
871 # FIXME - why not use GetAuthorisedValues ??
873 sub get_notforloan_label_of {
874 my $dbh = C4::Context->dbh;
877 SELECT authorised_value
878 FROM marc_subfield_structure
879 WHERE kohafield = \'items.notforloan\'
882 my $sth = $dbh->prepare($query);
884 my ($statuscode) = $sth->fetchrow_array();
889 FROM authorised_values
892 $sth = $dbh->prepare($query);
893 $sth->execute($statuscode);
894 my %notforloan_label_of;
895 while ( my $row = $sth->fetchrow_hashref ) {
896 $notforloan_label_of{ $row->{authorised_value} } = $row->{lib};
900 return \%notforloan_label_of;
903 =head2 displayServers
905 my $servers = displayServers();
906 my $servers = displayServers( $position );
907 my $servers = displayServers( $position, $type );
909 displayServers returns a listref of hashrefs, each containing
910 information about available z3950 servers. Each hashref has a format
914 'checked' => 'checked',
915 'encoding' => 'utf8',
917 'id' => 'LIBRARY OF CONGRESS',
921 'value' => 'lx2.loc.gov:210/',
928 my ( $position, $type ) = @_;
929 my $dbh = C4::Context->dbh;
931 my $strsth = 'SELECT * FROM z3950servers';
936 push @bind_params, $position;
937 push @where_clauses, ' position = ? ';
941 push @bind_params, $type;
942 push @where_clauses, ' type = ? ';
945 # reassemble where clause from where clause pieces
946 if (@where_clauses) {
947 $strsth .= ' WHERE ' . join( ' AND ', @where_clauses );
950 my $rq = $dbh->prepare($strsth);
951 $rq->execute(@bind_params);
952 my @primaryserverloop;
954 while ( my $data = $rq->fetchrow_hashref ) {
955 push @primaryserverloop,
956 { label => $data->{description},
959 value => $data->{host} . ":" . $data->{port} . "/" . $data->{database},
960 encoding => ( $data->{encoding} ? $data->{encoding} : "iso-5426" ),
961 checked => "checked",
962 icon => $data->{icon},
963 zed => $data->{type} eq 'zed',
964 opensearch => $data->{type} eq 'opensearch'
967 return \@primaryserverloop;
971 =head2 GetKohaImageurlFromAuthorisedValues
973 $authhorised_value = GetKohaImageurlFromAuthorisedValues( $category, $authvalcode );
975 Return the first url of the authorised value image represented by $lib.
979 sub GetKohaImageurlFromAuthorisedValues {
980 my ( $category, $lib ) = @_;
981 my $dbh = C4::Context->dbh;
982 my $sth = $dbh->prepare("SELECT imageurl FROM authorised_values WHERE category=? AND lib =?");
983 $sth->execute( $category, $lib );
984 while ( my $data = $sth->fetchrow_hashref ) {
985 return $data->{'imageurl'};
989 =head2 GetAuthValCode
991 $authvalcode = GetAuthValCode($kohafield,$frameworkcode);
996 my ($kohafield,$fwcode) = @_;
997 my $dbh = C4::Context->dbh;
998 $fwcode='' unless $fwcode;
999 my $sth = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield=? and frameworkcode=?');
1000 $sth->execute($kohafield,$fwcode);
1001 my ($authvalcode) = $sth->fetchrow_array;
1002 return $authvalcode;
1005 =head2 GetAuthValCodeFromField
1007 $authvalcode = GetAuthValCodeFromField($field,$subfield,$frameworkcode);
1009 C<$subfield> can be undefined
1013 sub GetAuthValCodeFromField {
1014 my ($field,$subfield,$fwcode) = @_;
1015 my $dbh = C4::Context->dbh;
1016 $fwcode='' unless $fwcode;
1018 if (defined $subfield) {
1019 $sth = $dbh->prepare('select authorised_value from marc_subfield_structure where tagfield=? and tagsubfield=? and frameworkcode=?');
1020 $sth->execute($field,$subfield,$fwcode);
1022 $sth = $dbh->prepare('select authorised_value from marc_tag_structure where tagfield=? and frameworkcode=?');
1023 $sth->execute($field,$fwcode);
1025 my ($authvalcode) = $sth->fetchrow_array;
1026 return $authvalcode;
1029 =head2 GetAuthorisedValues
1031 $authvalues = GetAuthorisedValues([$category], [$selected]);
1033 This function returns all authorised values from the'authorised_value' table in a reference to array of hashrefs.
1035 C<$category> returns authorised values for just one category (optional).
1037 C<$opac> If set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1041 sub GetAuthorisedValues {
1042 my ( $category, $selected, $opac ) = @_;
1043 my $branch_limit = C4::Context->userenv ? C4::Context->userenv->{"branch"} : "";
1045 my $dbh = C4::Context->dbh;
1048 FROM authorised_values
1051 LEFT JOIN authorised_values_branches ON ( id = av_id )
1056 push @where_strings, "category = ?";
1057 push @where_args, $category;
1060 push @where_strings, "( branchcode = ? OR branchcode IS NULL )";
1061 push @where_args, $branch_limit;
1063 if(@where_strings > 0) {
1064 $query .= " WHERE " . join(" AND ", @where_strings);
1066 $query .= " GROUP BY lib ORDER BY category, lib, lib_opac";
1068 my $sth = $dbh->prepare($query);
1070 $sth->execute( @where_args );
1071 while (my $data=$sth->fetchrow_hashref) {
1072 if ( defined $selected and $selected eq $data->{authorised_value} ) {
1073 $data->{selected} = 1;
1076 $data->{selected} = 0;
1079 if ($opac && $data->{lib_opac}) {
1080 $data->{lib} = $data->{lib_opac};
1082 push @results, $data;
1088 =head2 GetAuthorisedValueCategories
1090 $auth_categories = GetAuthorisedValueCategories();
1092 Return an arrayref of all of the available authorised
1097 sub GetAuthorisedValueCategories {
1098 my $dbh = C4::Context->dbh;
1099 my $sth = $dbh->prepare("SELECT DISTINCT category FROM authorised_values ORDER BY category");
1102 while (defined (my $category = $sth->fetchrow_array) ) {
1103 push @results, $category;
1108 =head2 GetAuthorisedValueByCode
1110 $authhorised_value = GetAuthorisedValueByCode( $category, $authvalcode );
1112 Return the lib attribute from authorised_values from the row identified
1113 by the passed category and code
1117 sub GetAuthorisedValueByCode {
1118 my ( $category, $authvalcode, $opac ) = @_;
1120 my $field = $opac ? 'lib_opac' : 'lib';
1121 my $dbh = C4::Context->dbh;
1122 my $sth = $dbh->prepare("SELECT $field FROM authorised_values WHERE category=? AND authorised_value =?");
1123 $sth->execute( $category, $authvalcode );
1124 while ( my $data = $sth->fetchrow_hashref ) {
1125 return $data->{ $field };
1129 =head2 GetKohaAuthorisedValues
1131 Takes $kohafield, $fwcode as parameters.
1133 If $opac parameter is set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1135 Returns hashref of Code => description
1137 Returns undef if no authorised value category is defined for the kohafield.
1141 sub GetKohaAuthorisedValues {
1142 my ($kohafield,$fwcode,$opac) = @_;
1143 $fwcode='' unless $fwcode;
1145 my $dbh = C4::Context->dbh;
1146 my $avcode = GetAuthValCode($kohafield,$fwcode);
1148 my $sth = $dbh->prepare("select authorised_value, lib, lib_opac from authorised_values where category=? ");
1149 $sth->execute($avcode);
1150 while ( my ($val, $lib, $lib_opac) = $sth->fetchrow_array ) {
1151 $values{$val} = ($opac && $lib_opac) ? $lib_opac : $lib;
1159 =head2 GetKohaAuthorisedValuesFromField
1161 Takes $field, $subfield, $fwcode as parameters.
1163 If $opac parameter is set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1164 $subfield can be undefined
1166 Returns hashref of Code => description
1168 Returns undef if no authorised value category is defined for the given field and subfield
1172 sub GetKohaAuthorisedValuesFromField {
1173 my ($field, $subfield, $fwcode,$opac) = @_;
1174 $fwcode='' unless $fwcode;
1176 my $dbh = C4::Context->dbh;
1177 my $avcode = GetAuthValCodeFromField($field, $subfield, $fwcode);
1179 my $sth = $dbh->prepare("select authorised_value, lib, lib_opac from authorised_values where category=? ");
1180 $sth->execute($avcode);
1181 while ( my ($val, $lib, $lib_opac) = $sth->fetchrow_array ) {
1182 $values{$val} = ($opac && $lib_opac) ? $lib_opac : $lib;
1192 my $escaped_string = C4::Koha::xml_escape($string);
1194 Convert &, <, >, ', and " in a string to XML entities
1200 return '' unless defined $str;
1201 $str =~ s/&/&/g;
1204 $str =~ s/'/'/g;
1205 $str =~ s/"/"/g;
1209 =head2 GetKohaAuthorisedValueLib
1211 Takes $category, $authorised_value as parameters.
1213 If $opac parameter is set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1215 Returns authorised value description
1219 sub GetKohaAuthorisedValueLib {
1220 my ($category,$authorised_value,$opac) = @_;
1222 my $dbh = C4::Context->dbh;
1223 my $sth = $dbh->prepare("select lib, lib_opac from authorised_values where category=? and authorised_value=?");
1224 $sth->execute($category,$authorised_value);
1225 my $data = $sth->fetchrow_hashref;
1226 $value = ($opac && $$data{'lib_opac'}) ? $$data{'lib_opac'} : $$data{'lib'};
1230 =head2 AddAuthorisedValue
1232 AddAuthorisedValue($category, $authorised_value, $lib, $lib_opac, $imageurl);
1234 Create a new authorised value.
1238 sub AddAuthorisedValue {
1239 my ($category, $authorised_value, $lib, $lib_opac, $imageurl) = @_;
1241 my $dbh = C4::Context->dbh;
1243 INSERT INTO authorised_values (category, authorised_value, lib, lib_opac, imageurl)
1246 my $sth = $dbh->prepare($query);
1247 $sth->execute($category, $authorised_value, $lib, $lib_opac, $imageurl);
1250 =head2 display_marc_indicators
1252 my $display_form = C4::Koha::display_marc_indicators($field);
1254 C<$field> is a MARC::Field object
1256 Generate a display form of the indicators of a variable
1257 MARC field, replacing any blanks with '#'.
1261 sub display_marc_indicators {
1263 my $indicators = '';
1264 if ($field->tag() >= 10) {
1265 $indicators = $field->indicator(1) . $field->indicator(2);
1266 $indicators =~ s/ /#/g;
1271 sub GetNormalizedUPC {
1272 my ($record,$marcflavour) = @_;
1275 if ($marcflavour eq 'UNIMARC') {
1276 @fields = $record->field('072');
1277 foreach my $field (@fields) {
1278 my $upc = _normalize_match_point($field->subfield('a'));
1285 else { # assume marc21 if not unimarc
1286 @fields = $record->field('024');
1287 foreach my $field (@fields) {
1288 my $indicator = $field->indicator(1);
1289 my $upc = _normalize_match_point($field->subfield('a'));
1290 if ($indicator == 1 and $upc ne '') {
1297 # Normalizes and returns the first valid ISBN found in the record
1298 # ISBN13 are converted into ISBN10. This is required to get some book cover images.
1299 sub GetNormalizedISBN {
1300 my ($isbn,$record,$marcflavour) = @_;
1303 # Koha attempts to store multiple ISBNs in biblioitems.isbn, separated by " | "
1304 # anything after " | " should be removed, along with the delimiter
1305 $isbn =~ s/(.*)( \| )(.*)/$1/;
1306 return _isbn_cleanup($isbn);
1308 return unless $record;
1310 if ($marcflavour eq 'UNIMARC') {
1311 @fields = $record->field('010');
1312 foreach my $field (@fields) {
1313 my $isbn = $field->subfield('a');
1315 return _isbn_cleanup($isbn);
1321 else { # assume marc21 if not unimarc
1322 @fields = $record->field('020');
1323 foreach my $field (@fields) {
1324 $isbn = $field->subfield('a');
1326 return _isbn_cleanup($isbn);
1334 sub GetNormalizedEAN {
1335 my ($record,$marcflavour) = @_;
1338 if ($marcflavour eq 'UNIMARC') {
1339 @fields = $record->field('073');
1340 foreach my $field (@fields) {
1341 $ean = _normalize_match_point($field->subfield('a'));
1347 else { # assume marc21 if not unimarc
1348 @fields = $record->field('024');
1349 foreach my $field (@fields) {
1350 my $indicator = $field->indicator(1);
1351 $ean = _normalize_match_point($field->subfield('a'));
1352 if ($indicator == 3 and $ean ne '') {
1358 sub GetNormalizedOCLCNumber {
1359 my ($record,$marcflavour) = @_;
1362 if ($marcflavour eq 'UNIMARC') {
1363 # TODO: add UNIMARC fields
1365 else { # assume marc21 if not unimarc
1366 @fields = $record->field('035');
1367 foreach my $field (@fields) {
1368 $oclc = $field->subfield('a');
1369 if ($oclc =~ /OCoLC/) {
1370 $oclc =~ s/\(OCoLC\)//;
1379 =head2 GetDailyQuote($opts)
1381 Takes a hashref of options
1383 Currently supported options are:
1385 'id' An exact quote id
1386 'random' Select a random quote
1387 noop When no option is passed in, this sub will return the quote timestamped for the current day
1389 The function returns an anonymous hash following this format:
1392 'source' => 'source-of-quote',
1393 'timestamp' => 'timestamp-value',
1394 'text' => 'text-of-quote',
1400 # This is definitely a candidate for some sort of caching once we finally settle caching/persistence issues...
1401 # at least for default option
1405 my $dbh = C4::Context->dbh;
1410 $query = 'SELECT * FROM quotes WHERE id = ?';
1411 $sth = $dbh->prepare($query);
1412 $sth->execute($opts{'id'});
1413 $quote = $sth->fetchrow_hashref();
1415 elsif ($opts{'random'}) {
1416 # Fall through... we also return a random quote as a catch-all if all else fails
1419 $query = 'SELECT * FROM quotes WHERE timestamp LIKE CONCAT(CURRENT_DATE,\'%\') ORDER BY timestamp DESC LIMIT 0,1';
1420 $sth = $dbh->prepare($query);
1422 $quote = $sth->fetchrow_hashref();
1424 unless ($quote) { # if there are not matches, choose a random quote
1425 # get a list of all available quote ids
1426 $sth = C4::Context->dbh->prepare('SELECT count(*) FROM quotes;');
1428 my $range = ($sth->fetchrow_array)[0];
1430 # chose a random id within that range if there is more than one quote
1431 my $id = int(rand($range));
1433 $query = 'SELECT * FROM quotes WHERE id = ?;';
1434 $sth = C4::Context->dbh->prepare($query);
1438 $query = 'SELECT * FROM quotes;';
1439 $sth = C4::Context->dbh->prepare($query);
1442 $quote = $sth->fetchrow_hashref();
1443 # update the timestamp for that quote
1444 $query = 'UPDATE quotes SET timestamp = ? WHERE id = ?';
1445 $sth = C4::Context->dbh->prepare($query);
1446 $sth->execute(DateTime::Format::MySQL->format_datetime(DateTime->now), $quote->{'id'});
1451 sub _normalize_match_point {
1452 my $match_point = shift;
1453 (my $normalized_match_point) = $match_point =~ /([\d-]*[X]*)/;
1454 $normalized_match_point =~ s/-//g;
1456 return $normalized_match_point;
1460 require Business::ISBN;
1461 my $isbn = Business::ISBN->new( $_[0] );
1463 $isbn = $isbn->as_isbn10 if $isbn->type eq 'ISBN13';
1464 if (defined $isbn) {
1465 return $isbn->as_string([]);