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
10 # under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 3 of the License, or
12 # (at your option) any later version.
14 # Koha is distributed in the hope that it will be useful, but
15 # WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with Koha; if not, see <http://www.gnu.org/licenses>.
24 #use warnings; FIXME - Bug 2505
27 use C4
::Branch
qw(GetBranchesCount);
29 use Koha
::DateUtils
qw(dt_from_string);
30 use DateTime
::Format
::MySQL
;
32 use autouse
'Data::cselectall_arrayref' => qw(Dumper);
33 use DBI
qw(:sql_types);
35 use vars
qw($VERSION @ISA @EXPORT @EXPORT_OK $DEBUG);
38 $VERSION = 3.07.00.049;
43 &subfield_is_koha_internal_p
44 &GetPrinters &GetPrinter
45 &GetItemTypes &getitemtypeinfo
46 &GetItemTypesCategorized &GetItemTypesByCategory
47 &GetSupportName &GetSupportList
49 &getframeworks &getframeworkinfo
51 &getauthtypes &getauthtype
57 &get_notforloan_label_of
60 &getitemtypeimagelocation
62 &GetAuthorisedValueCategories
63 &IsAuthorisedValueCategory
64 &GetKohaAuthorisedValues
65 &GetKohaAuthorisedValuesFromField
66 &GetKohaAuthorisedValuesMapping
67 &GetKohaAuthorisedValueLib
68 &GetAuthorisedValueByCode
69 &GetKohaImageurlFromAuthorisedValues
75 &GetNormalizedOCLCNumber
85 @EXPORT_OK = qw( GetDailyQuote );
90 C4::Koha - Perl Module containing convenience functions for Koha scripts
98 Koha.pm provides many functions for Koha scripts.
106 $slash_date = &slashifyDate($dash_date);
108 Takes a string of the form "DD-MM-YYYY" (or anything separated by
109 dashes), converts it to the form "YYYY/MM/DD", and returns the result.
115 # accepts a date of the form xx-xx-xx[xx] and returns it in the
117 my @dateOut = split( '-', shift );
118 return ("$dateOut[2]/$dateOut[1]/$dateOut[0]");
121 # FIXME.. this should be moved to a MARC-specific module
122 sub subfield_is_koha_internal_p
{
125 # We could match on 'lib' and 'tab' (and 'mandatory', & more to come!)
126 # But real MARC subfields are always single-character
127 # so it really is safer just to check the length
129 return length $subfield != 1;
132 =head2 GetSupportName
134 $itemtypename = &GetSupportName($codestring);
136 Returns a string with the name of the itemtype.
142 return if (! $codestring);
144 my $advanced_search_types = C4
::Context
->preference("AdvancedSearchTypes");
145 if (!$advanced_search_types or $advanced_search_types eq 'itemtypes') {
152 my $sth = C4
::Context
->dbh->prepare($query);
153 $sth->execute($codestring);
154 ($resultstring)=$sth->fetchrow;
155 return $resultstring;
158 C4
::Context
->dbh->prepare(
159 "SELECT lib FROM authorised_values WHERE category = ? AND authorised_value = ?"
161 $sth->execute( $advanced_search_types, $codestring );
162 my $data = $sth->fetchrow_hashref;
163 return $$data{'lib'};
167 =head2 GetSupportList
169 $itemtypes = &GetSupportList();
171 Returns an array ref containing informations about Support (since itemtype is rather a circulation code when item-level-itypes is used).
173 build a HTML select with the following code :
175 =head3 in PERL SCRIPT
177 my $itemtypes = GetSupportList();
178 $template->param(itemtypeloop => $itemtypes);
182 <select name="itemtype" id="itemtype">
183 <option value=""></option>
184 [% FOREACH itemtypeloo IN itemtypeloop %]
185 [% IF ( itemtypeloo.selected ) %]
186 <option value="[% itemtypeloo.itemtype %]" selected="selected">[% itemtypeloo.description %]</option>
188 <option value="[% itemtypeloo.itemtype %]">[% itemtypeloo.description %]</option>
196 my $advanced_search_types = C4
::Context
->preference("AdvancedSearchTypes");
197 if (!$advanced_search_types or $advanced_search_types =~ /itemtypes/) {
203 my $sth = C4
::Context
->dbh->prepare($query);
205 return $sth->fetchall_arrayref({});
207 my $advsearchtypes = GetAuthorisedValues
($advanced_search_types);
208 my @results= map {{itemtype
=>$$_{authorised_value
},description
=>$$_{lib
},imageurl
=>$$_{imageurl
}}} @
$advsearchtypes;
214 $itemtypes = &GetItemTypes( style => $style );
216 Returns information about existing itemtypes.
219 style: either 'array' or 'hash', defaults to 'hash'.
220 'array' returns an arrayref,
221 'hash' return a hashref with the itemtype value as the key
223 build a HTML select with the following code :
225 =head3 in PERL SCRIPT
227 my $itemtypes = GetItemTypes;
229 foreach my $thisitemtype (sort keys %$itemtypes) {
230 my $selected = 1 if $thisitemtype eq $itemtype;
231 my %row =(value => $thisitemtype,
232 selected => $selected,
233 description => $itemtypes->{$thisitemtype}->{'description'},
235 push @itemtypesloop, \%row;
237 $template->param(itemtypeloop => \@itemtypesloop);
241 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
242 <select name="itemtype">
243 <option value="">Default</option>
244 <!-- TMPL_LOOP name="itemtypeloop" -->
245 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="description" --></option>
248 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
249 <input type="submit" value="OK" class="button">
256 my $style = defined( $params{'style'} ) ?
$params{'style'} : 'hash';
258 # returns a reference to a hash of references to itemtypes...
260 my $dbh = C4
::Context
->dbh;
265 my $sth = $dbh->prepare($query);
268 if ( $style eq 'hash' ) {
269 while ( my $IT = $sth->fetchrow_hashref ) {
270 $itemtypes{ $IT->{'itemtype'} } = $IT;
272 return ( \
%itemtypes );
274 return $sth->fetchall_arrayref({});
278 =head2 GetItemTypesCategorized
280 $categories = GetItemTypesCategorized();
282 Returns a hashref containing search categories.
283 A search category will be put in the hash if at least one of its itemtypes is visible in OPAC.
284 The categories must be part of Authorized Values (DOCTYPECAT)
288 sub GetItemTypesCategorized
{
289 my $dbh = C4
::Context
->dbh;
290 # Order is important, so that partially hidden (some items are not visible in OPAC) search
291 # categories will be visible. hideinopac=0 must be last.
293 SELECT itemtype
, description
, imageurl
, hideinopac
, 0 as
'iscat' FROM itemtypes WHERE ISNULL
(searchcategory
) or length(searchcategory
) = 0
295 SELECT DISTINCT searchcategory AS
`itemtype`,
296 authorised_values
.lib_opac AS description
,
297 authorised_values
.imageurl AS imageurl
,
298 hideinopac
, 1 as
'iscat'
300 LEFT JOIN authorised_values ON searchcategory
= authorised_value
301 WHERE searchcategory
> '' and hideinopac
=1
303 SELECT DISTINCT searchcategory AS
`itemtype`,
304 authorised_values
.lib_opac AS description
,
305 authorised_values
.imageurl AS imageurl
,
306 hideinopac
, 1 as
'iscat'
308 LEFT JOIN authorised_values ON searchcategory
= authorised_value
309 WHERE searchcategory
> '' and hideinopac
=0
311 return ($dbh->selectall_hashref($query,'itemtype'));
314 =head2 GetItemTypesByCategory
316 @results = GetItemTypesByCategory( $searchcategory );
318 Returns the itemtype code of all itemtypes included in a searchcategory.
322 sub GetItemTypesByCategory
{
326 my $dbh = C4
::Context
->dbh;
327 my $query = qq|SELECT itemtype FROM itemtypes WHERE searchcategory
=?
|;
328 my $tmp=$dbh->selectcol_arrayref($query,undef,$category);
332 sub get_itemtypeinfos_of
{
335 my $placeholders = join( ', ', map { '?' } @itemtypes );
336 my $query = <<"END_SQL";
342 WHERE itemtype IN ( $placeholders )
345 return get_infos_of( $query, 'itemtype', undef, \@itemtypes );
350 $authtypes = &getauthtypes();
352 Returns information about existing authtypes.
354 build a HTML select with the following code :
356 =head3 in PERL SCRIPT
358 my $authtypes = getauthtypes;
360 foreach my $thisauthtype (keys %$authtypes) {
361 my $selected = 1 if $thisauthtype eq $authtype;
362 my %row =(value => $thisauthtype,
363 selected => $selected,
364 authtypetext => $authtypes->{$thisauthtype}->{'authtypetext'},
366 push @authtypesloop, \%row;
368 $template->param(itemtypeloop => \@itemtypesloop);
372 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
373 <select name="authtype">
374 <!-- TMPL_LOOP name="authtypeloop" -->
375 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="authtypetext" --></option>
378 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
379 <input type="submit" value="OK" class="button">
387 # returns a reference to a hash of references to authtypes...
389 my $dbh = C4::Context->dbh;
390 my $sth = $dbh->prepare("select * from auth_types order by authtypetext");
392 while ( my $IT = $sth->fetchrow_hashref ) {
393 $authtypes{ $IT->{'authtypecode'} } = $IT;
395 return ( \%authtypes );
399 my ($authtypecode) = @_;
401 # returns a reference to a hash of references to authtypes...
403 my $dbh = C4::Context->dbh;
404 my $sth = $dbh->prepare("select * from auth_types where authtypecode=?");
405 $sth->execute($authtypecode);
406 my $res = $sth->fetchrow_hashref;
412 $frameworks = &getframework();
414 Returns information about existing frameworks
416 build a HTML select with the following code :
418 =head3 in PERL SCRIPT
420 my $frameworks = getframeworks();
422 foreach my $thisframework (keys %$frameworks) {
423 my $selected = 1 if $thisframework eq $frameworkcode;
425 value => $thisframework,
426 selected => $selected,
427 description => $frameworks->{$thisframework}->{'frameworktext'},
429 push @frameworksloop, \%row;
431 $template->param(frameworkloop => \@frameworksloop);
435 <form action="[% script_name %] method=post>
436 <select name="frameworkcode">
437 <option value="">Default</option>
438 [% FOREACH framework IN frameworkloop %]
439 [% IF ( framework.selected ) %]
440 <option value="[% framework.value %]" selected="selected">[% framework.description %]</option>
442 <option value="[% framework.value %]">[% framework.description %]</option>
446 <input type
=text name
=searchfield value
="[% searchfield %]">
447 <input type
="submit" value
="OK" class="button">
454 # returns a reference to a hash of references to branches...
456 my $dbh = C4
::Context
->dbh;
457 my $sth = $dbh->prepare("select * from biblio_framework");
459 while ( my $IT = $sth->fetchrow_hashref ) {
460 $itemtypes{ $IT->{'frameworkcode'} } = $IT;
462 return ( \
%itemtypes );
465 =head2 GetFrameworksLoop
467 $frameworks = GetFrameworksLoop( $frameworkcode );
469 Returns the loop suggested on getframework(), but ordered by framework description.
471 build a HTML select with the following code :
473 =head3 in PERL SCRIPT
475 $template->param( frameworkloop => GetFrameworksLoop( $frameworkcode ) );
479 Same as getframework()
481 <form action="[% script_name %] method=post>
482 <select name="frameworkcode">
483 <option value="">Default</option>
484 [% FOREACH framework IN frameworkloop %]
485 [% IF ( framework.selected ) %]
486 <option value="[% framework.value %]" selected="selected">[% framework.description %]</option>
488 <option value="[% framework.value %]">[% framework.description %]</option>
492 <input type=text name=searchfield value="[% searchfield %]">
493 <input type="submit" value="OK" class="button">
498 sub GetFrameworksLoop
{
499 my $frameworkcode = shift;
500 my $frameworks = getframeworks
();
502 foreach my $thisframework (sort { uc($frameworks->{$a}->{'frameworktext'}) cmp uc($frameworks->{$b}->{'frameworktext'}) } keys %$frameworks) {
503 my $selected = ( $thisframework eq $frameworkcode ) ?
1 : undef;
505 value
=> $thisframework,
506 selected
=> $selected,
507 description
=> $frameworks->{$thisframework}->{'frameworktext'},
509 push @frameworkloop, \
%row;
511 return \
@frameworkloop;
514 =head2 getframeworkinfo
516 $frameworkinfo = &getframeworkinfo($frameworkcode);
518 Returns information about an frameworkcode.
522 sub getframeworkinfo
{
523 my ($frameworkcode) = @_;
524 my $dbh = C4
::Context
->dbh;
526 $dbh->prepare("select * from biblio_framework where frameworkcode=?");
527 $sth->execute($frameworkcode);
528 my $res = $sth->fetchrow_hashref;
532 =head2 getitemtypeinfo
534 $itemtype = &getitemtypeinfo($itemtype, [$interface]);
536 Returns information about an itemtype. The optional $interface argument
537 sets which interface ('opac' or 'intranet') to return the imageurl for.
538 Defaults to intranet.
542 sub getitemtypeinfo
{
543 my ($itemtype, $interface) = @_;
544 my $dbh = C4
::Context
->dbh;
545 my $sth = $dbh->prepare("select * from itemtypes where itemtype=?");
546 $sth->execute($itemtype);
547 my $res = $sth->fetchrow_hashref;
549 $res->{imageurl
} = getitemtypeimagelocation
( ( ( defined $interface && $interface eq 'opac' ) ?
'opac' : 'intranet' ), $res->{imageurl
} );
554 =head2 getitemtypeimagedir
556 my $directory = getitemtypeimagedir( 'opac' );
558 pass in 'opac' or 'intranet'. Defaults to 'opac'.
560 returns the full path to the appropriate directory containing images.
564 sub getitemtypeimagedir
{
565 my $src = shift || 'opac';
566 if ($src eq 'intranet') {
567 return C4
::Context
->config('intrahtdocs') . '/' .C4
::Context
->preference('template') . '/img/itemtypeimg';
569 return C4
::Context
->config('opachtdocs') . '/' . C4
::Context
->preference('opacthemes') . '/itemtypeimg';
573 sub getitemtypeimagesrc
{
574 my $src = shift || 'opac';
575 if ($src eq 'intranet') {
576 return '/intranet-tmpl' . '/' . C4
::Context
->preference('template') . '/img/itemtypeimg';
578 return '/opac-tmpl' . '/' . C4
::Context
->preference('opacthemes') . '/itemtypeimg';
582 sub getitemtypeimagelocation
{
583 my ( $src, $image ) = @_;
585 return '' if ( !$image );
588 my $scheme = ( URI
::Split
::uri_split
( $image ) )[0];
590 return $image if ( $scheme );
592 return getitemtypeimagesrc
( $src ) . '/' . $image;
595 =head3 _getImagesFromDirectory
597 Find all of the image files in a directory in the filesystem
599 parameters: a directory name
601 returns: a list of images in that directory.
603 Notes: this does not traverse into subdirectories. See
604 _getSubdirectoryNames for help with that.
605 Images are assumed to be files with .gif or .png file extensions.
606 The image names returned do not have the directory name on them.
610 sub _getImagesFromDirectory
{
611 my $directoryname = shift;
612 return unless defined $directoryname;
613 return unless -d
$directoryname;
615 if ( opendir ( my $dh, $directoryname ) ) {
616 my @images = grep { /\.(gif|png)$/i } readdir( $dh );
618 @images = sort(@images);
621 warn "unable to opendir $directoryname: $!";
626 =head3 _getSubdirectoryNames
628 Find all of the directories in a directory in the filesystem
630 parameters: a directory name
632 returns: a list of subdirectories in that directory.
634 Notes: this does not traverse into subdirectories. Only the first
635 level of subdirectories are returned.
636 The directory names returned don't have the parent directory name on them.
640 sub _getSubdirectoryNames
{
641 my $directoryname = shift;
642 return unless defined $directoryname;
643 return unless -d
$directoryname;
645 if ( opendir ( my $dh, $directoryname ) ) {
646 my @directories = grep { -d File
::Spec
->catfile( $directoryname, $_ ) && ! ( /^\./ ) } readdir( $dh );
650 warn "unable to opendir $directoryname: $!";
657 returns: a listref of hashrefs. Each hash represents another collection of images.
659 { imagesetname => 'npl', # the name of the image set (npl is the original one)
660 images => listref of image hashrefs
663 each image is represented by a hashref like this:
665 { KohaImage => 'npl/image.gif',
666 StaffImageUrl => '/intranet-tmpl/prog/img/itemtypeimg/npl/image.gif',
667 OpacImageURL => '/opac-tmpl/prog/itemtypeimg/npl/image.gif'
668 checked => 0 or 1: was this the image passed to this method?
669 Note: I'd like to remove this somehow.
676 my $checked = $params{'checked'} || '';
678 my $paths = { staff
=> { filesystem
=> getitemtypeimagedir
('intranet'),
679 url
=> getitemtypeimagesrc
('intranet'),
681 opac
=> { filesystem
=> getitemtypeimagedir
('opac'),
682 url
=> getitemtypeimagesrc
('opac'),
686 my @imagesets = (); # list of hasrefs of image set data to pass to template
687 my @subdirectories = _getSubdirectoryNames
( $paths->{'staff'}{'filesystem'} );
688 foreach my $imagesubdir ( @subdirectories ) {
689 warn $imagesubdir if $DEBUG;
690 my @imagelist = (); # hashrefs of image info
691 my @imagenames = _getImagesFromDirectory
( File
::Spec
->catfile( $paths->{'staff'}{'filesystem'}, $imagesubdir ) );
692 my $imagesetactive = 0;
693 foreach my $thisimage ( @imagenames ) {
695 { KohaImage
=> "$imagesubdir/$thisimage",
696 StaffImageUrl
=> join( '/', $paths->{'staff'}{'url'}, $imagesubdir, $thisimage ),
697 OpacImageUrl
=> join( '/', $paths->{'opac'}{'url'}, $imagesubdir, $thisimage ),
698 checked
=> "$imagesubdir/$thisimage" eq $checked ?
1 : 0,
701 $imagesetactive = 1 if "$imagesubdir/$thisimage" eq $checked;
703 push @imagesets, { imagesetname
=> $imagesubdir,
704 imagesetactive
=> $imagesetactive,
705 images
=> \
@imagelist };
713 $printers = &GetPrinters();
714 @queues = keys %$printers;
716 Returns information about existing printer queues.
718 C<$printers> is a reference-to-hash whose keys are the print queues
719 defined in the printers table of the Koha database. The values are
720 references-to-hash, whose keys are the fields in the printers table.
726 my $dbh = C4
::Context
->dbh;
727 my $sth = $dbh->prepare("select * from printers");
729 while ( my $printer = $sth->fetchrow_hashref ) {
730 $printers{ $printer->{'printqueue'} } = $printer;
732 return ( \
%printers );
737 $printer = GetPrinter( $query, $printers );
742 my ( $query, $printers ) = @_; # get printer for this query from printers
743 my $printer = $query->param('printer');
744 my %cookie = $query->cookie('userenv');
745 ($printer) || ( $printer = $cookie{'printer'} ) || ( $printer = '' );
746 ( $printers->{$printer} ) || ( $printer = ( keys %$printers )[0] );
752 Returns the number of pages to display in a pagination bar, given the number
753 of items and the number of items per page.
758 my ( $nb_items, $nb_items_per_page ) = @_;
760 return int( ( $nb_items - 1 ) / $nb_items_per_page ) + 1;
765 (@themes) = &getallthemes('opac');
766 (@themes) = &getallthemes('intranet');
768 Returns an array of all available themes.
776 if ( $type eq 'intranet' ) {
777 $htdocs = C4
::Context
->config('intrahtdocs');
780 $htdocs = C4
::Context
->config('opachtdocs');
782 opendir D
, "$htdocs";
783 my @dirlist = readdir D
;
784 foreach my $directory (@dirlist) {
785 next if $directory eq 'lib';
786 -d
"$htdocs/$directory/en" and push @themes, $directory;
793 if ( C4
::Context
->preference("marcflavour") eq "UNIMARC" ) {
798 tags
=> [ qw
/ 600ab 601ab 602a 604at 605a 606ax 610a / ],
804 tags
=> [ qw
/ 607a / ],
810 tags
=> [ qw
/ 500a 501a 503a / ],
816 tags
=> [ qw
/ 700ab 701ab 702ab / ],
817 sep
=> C4
::Context
->preference("UNIMARCAuthorsFacetsSeparator"),
822 tags
=> [ qw
/ 225a / ],
828 tags
=> [ qw
/ 995e / ],
832 unless ( C4
::Context
->preference("singleBranchMode")
833 || GetBranchesCount
() == 1 )
835 my $DisplayLibraryFacets = C4
::Context
->preference('DisplayLibraryFacets');
836 if ( $DisplayLibraryFacets eq 'both'
837 || $DisplayLibraryFacets eq 'holding' )
842 idx
=> 'holdingbranch',
843 label
=> 'HoldingLibrary',
844 tags
=> [qw
/ 995c /],
849 if ( $DisplayLibraryFacets eq 'both'
850 || $DisplayLibraryFacets eq 'home' )
856 label
=> 'HomeLibrary',
857 tags
=> [qw
/ 995b /],
868 tags
=> [ qw
/ 650a / ],
873 # label => 'People and Organizations',
874 # tags => [ qw/ 600a 610a 611a / ],
880 tags
=> [ qw
/ 651a / ],
886 tags
=> [ qw
/ 630a / ],
892 tags
=> [ qw
/ 100a 110a 700a / ],
898 tags
=> [ qw
/ 440a 490a / ],
903 label
=> 'ItemTypes',
904 tags
=> [ qw
/ 952y 942c / ],
910 tags
=> [ qw
/ 952c / ],
914 unless ( C4
::Context
->preference("singleBranchMode")
915 || GetBranchesCount
() == 1 )
917 my $DisplayLibraryFacets = C4
::Context
->preference('DisplayLibraryFacets');
918 if ( $DisplayLibraryFacets eq 'both'
919 || $DisplayLibraryFacets eq 'holding' )
924 idx
=> 'holdingbranch',
925 label
=> 'HoldingLibrary',
926 tags
=> [qw
/ 952b /],
931 if ( $DisplayLibraryFacets eq 'both'
932 || $DisplayLibraryFacets eq 'home' )
938 label
=> 'HomeLibrary',
939 tags
=> [qw
/ 952a /],
950 Return a href where a key is associated to a href. You give a query,
951 the name of the key among the fields returned by the query. If you
952 also give as third argument the name of the value, the function
953 returns a href of scalar. The optional 4th argument is an arrayref of
954 items passed to the C<execute()> call. It is designed to bind
955 parameters to any placeholders in your SQL.
964 # generic href of any information on the item, href of href.
965 my $iteminfos_of = get_infos_of($query, 'itemnumber');
966 print $iteminfos_of->{$itemnumber}{barcode};
968 # specific information, href of scalar
969 my $barcode_of_item = get_infos_of($query, 'itemnumber', 'barcode');
970 print $barcode_of_item->{$itemnumber};
975 my ( $query, $key_name, $value_name, $bind_params ) = @_;
977 my $dbh = C4
::Context
->dbh;
979 my $sth = $dbh->prepare($query);
980 $sth->execute( @
$bind_params );
983 while ( my $row = $sth->fetchrow_hashref ) {
984 if ( defined $value_name ) {
985 $infos_of{ $row->{$key_name} } = $row->{$value_name};
988 $infos_of{ $row->{$key_name} } = $row;
996 =head2 get_notforloan_label_of
998 my $notforloan_label_of = get_notforloan_label_of();
1000 Each authorised value of notforloan (information available in items and
1001 itemtypes) is link to a single label.
1003 Returns a href where keys are authorised values and values are corresponding
1006 foreach my $authorised_value (keys %{$notforloan_label_of}) {
1008 "authorised_value: %s => %s\n",
1010 $notforloan_label_of->{$authorised_value}
1016 # FIXME - why not use GetAuthorisedValues ??
1018 sub get_notforloan_label_of
{
1019 my $dbh = C4
::Context
->dbh;
1022 SELECT authorised_value
1023 FROM marc_subfield_structure
1024 WHERE kohafield = \'items.notforloan\'
1027 my $sth = $dbh->prepare($query);
1029 my ($statuscode) = $sth->fetchrow_array();
1034 FROM authorised_values
1037 $sth = $dbh->prepare($query);
1038 $sth->execute($statuscode);
1039 my %notforloan_label_of;
1040 while ( my $row = $sth->fetchrow_hashref ) {
1041 $notforloan_label_of{ $row->{authorised_value
} } = $row->{lib
};
1045 return \
%notforloan_label_of;
1048 =head2 displayServers
1050 my $servers = displayServers();
1051 my $servers = displayServers( $position );
1052 my $servers = displayServers( $position, $type );
1054 displayServers returns a listref of hashrefs, each containing
1055 information about available z3950 servers. Each hashref has a format
1059 'checked' => 'checked',
1060 'encoding' => 'utf8',
1062 'id' => 'LIBRARY OF CONGRESS',
1066 'value' => 'lx2.loc.gov:210/',
1072 sub displayServers
{
1073 my ( $position, $type ) = @_;
1074 my $dbh = C4
::Context
->dbh;
1076 my $strsth = 'SELECT * FROM z3950servers';
1081 push @bind_params, $position;
1082 push @where_clauses, ' position = ? ';
1086 push @bind_params, $type;
1087 push @where_clauses, ' type = ? ';
1090 # reassemble where clause from where clause pieces
1091 if (@where_clauses) {
1092 $strsth .= ' WHERE ' . join( ' AND ', @where_clauses );
1095 my $rq = $dbh->prepare($strsth);
1096 $rq->execute(@bind_params);
1097 my @primaryserverloop;
1099 while ( my $data = $rq->fetchrow_hashref ) {
1100 push @primaryserverloop,
1101 { label
=> $data->{description
},
1102 id
=> $data->{name
},
1104 value
=> $data->{host
} . ":" . $data->{port
} . "/" . $data->{database
},
1105 encoding
=> ( $data->{encoding
} ?
$data->{encoding
} : "iso-5426" ),
1106 checked
=> "checked",
1107 icon
=> $data->{icon
},
1108 zed
=> $data->{type
} eq 'zed',
1109 opensearch
=> $data->{type
} eq 'opensearch'
1112 return \
@primaryserverloop;
1116 =head2 GetKohaImageurlFromAuthorisedValues
1118 $authhorised_value = GetKohaImageurlFromAuthorisedValues( $category, $authvalcode );
1120 Return the first url of the authorised value image represented by $lib.
1124 sub GetKohaImageurlFromAuthorisedValues
{
1125 my ( $category, $lib ) = @_;
1126 my $dbh = C4
::Context
->dbh;
1127 my $sth = $dbh->prepare("SELECT imageurl FROM authorised_values WHERE category=? AND lib =?");
1128 $sth->execute( $category, $lib );
1129 while ( my $data = $sth->fetchrow_hashref ) {
1130 return $data->{'imageurl'};
1134 =head2 GetAuthValCode
1136 $authvalcode = GetAuthValCode($kohafield,$frameworkcode);
1140 sub GetAuthValCode
{
1141 my ($kohafield,$fwcode) = @_;
1142 my $dbh = C4
::Context
->dbh;
1143 $fwcode='' unless $fwcode;
1144 my $sth = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield=? and frameworkcode=?');
1145 $sth->execute($kohafield,$fwcode);
1146 my ($authvalcode) = $sth->fetchrow_array;
1147 return $authvalcode;
1150 =head2 GetAuthValCodeFromField
1152 $authvalcode = GetAuthValCodeFromField($field,$subfield,$frameworkcode);
1154 C<$subfield> can be undefined
1158 sub GetAuthValCodeFromField
{
1159 my ($field,$subfield,$fwcode) = @_;
1160 my $dbh = C4
::Context
->dbh;
1161 $fwcode='' unless $fwcode;
1163 if (defined $subfield) {
1164 $sth = $dbh->prepare('select authorised_value from marc_subfield_structure where tagfield=? and tagsubfield=? and frameworkcode=?');
1165 $sth->execute($field,$subfield,$fwcode);
1167 $sth = $dbh->prepare('select authorised_value from marc_tag_structure where tagfield=? and frameworkcode=?');
1168 $sth->execute($field,$fwcode);
1170 my ($authvalcode) = $sth->fetchrow_array;
1171 return $authvalcode;
1174 =head2 GetAuthorisedValues
1176 $authvalues = GetAuthorisedValues([$category], [$selected]);
1178 This function returns all authorised values from the'authorised_value' table in a reference to array of hashrefs.
1180 C<$category> returns authorised values for just one category (optional).
1182 C<$selected> adds a "selected => 1" entry to the hash if the
1183 authorised_value matches it. B<NOTE:> this feature should be considered
1184 deprecated as it may be removed in the future.
1186 C<$opac> If set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1190 sub GetAuthorisedValues
{
1191 my ( $category, $selected, $opac ) = @_;
1193 # TODO: the "selected" feature should be replaced by a utility function
1194 # somewhere else, it doesn't belong in here. For starters it makes
1195 # caching much more complicated. Or just let the UI logic handle it, it's
1198 # Is this cached already?
1199 $opac = $opac ?
1 : 0; # normalise to be safe
1201 C4
::Context
->userenv ? C4
::Context
->userenv->{"branch"} : "";
1202 my $selected_key = defined($selected) ?
$selected : '';
1204 "AuthorisedValues-$category-$selected_key-$opac-$branch_limit";
1205 my $cache = Koha
::Cache
->get_instance();
1206 my $result = $cache->get_from_cache($cache_key);
1207 return $result if $result;
1210 my $dbh = C4
::Context
->dbh;
1213 FROM authorised_values
1216 LEFT JOIN authorised_values_branches ON
( id
= av_id
)
1221 push @where_strings, "category = ?";
1222 push @where_args, $category;
1225 push @where_strings, "( branchcode = ? OR branchcode IS NULL )";
1226 push @where_args, $branch_limit;
1228 if(@where_strings > 0) {
1229 $query .= " WHERE " . join(" AND ", @where_strings);
1231 $query .= " GROUP BY lib";
1232 $query .= ' ORDER BY category, ' . (
1233 $opac ?
'COALESCE(lib_opac, lib)'
1237 my $sth = $dbh->prepare($query);
1239 $sth->execute( @where_args );
1240 while (my $data=$sth->fetchrow_hashref) {
1241 if ( defined $selected and $selected eq $data->{authorised_value
} ) {
1242 $data->{selected
} = 1;
1245 $data->{selected
} = 0;
1248 if ($opac && $data->{lib_opac
}) {
1249 $data->{lib
} = $data->{lib_opac
};
1251 push @results, $data;
1255 # We can't cache for long because of that "selected" thing which
1256 # makes it impossible to clear the cache without iterating through every
1257 # value, which sucks. This'll cover this request, and not a whole lot more.
1258 $cache->set_in_cache( $cache_key, \
@results, { deepcopy
=> 1, expiry
=> 5 } );
1262 =head2 GetAuthorisedValueCategories
1264 $auth_categories = GetAuthorisedValueCategories();
1266 Return an arrayref of all of the available authorised
1271 sub GetAuthorisedValueCategories
{
1272 my $dbh = C4
::Context
->dbh;
1273 my $sth = $dbh->prepare("SELECT DISTINCT category FROM authorised_values ORDER BY category");
1276 while (defined (my $category = $sth->fetchrow_array) ) {
1277 push @results, $category;
1282 =head2 IsAuthorisedValueCategory
1284 $is_auth_val_category = IsAuthorisedValueCategory($category);
1286 Returns whether a given category name is a valid one
1290 sub IsAuthorisedValueCategory
{
1291 my $category = shift;
1294 FROM authorised_values
1295 WHERE BINARY category=?
1298 my $sth = C4
::Context
->dbh->prepare($query);
1299 $sth->execute($category);
1300 $sth->fetchrow ?
return 1
1304 =head2 GetAuthorisedValueByCode
1306 $authorised_value = GetAuthorisedValueByCode( $category, $authvalcode, $opac );
1308 Return the lib attribute from authorised_values from the row identified
1309 by the passed category and code
1313 sub GetAuthorisedValueByCode
{
1314 my ( $category, $authvalcode, $opac ) = @_;
1316 my $field = $opac ?
'lib_opac' : 'lib';
1317 my $dbh = C4
::Context
->dbh;
1318 my $sth = $dbh->prepare("SELECT $field FROM authorised_values WHERE category=? AND authorised_value =?");
1319 $sth->execute( $category, $authvalcode );
1320 while ( my $data = $sth->fetchrow_hashref ) {
1321 return $data->{ $field };
1325 =head2 GetKohaAuthorisedValues
1327 Takes $kohafield, $fwcode as parameters.
1329 If $opac parameter is set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1331 Returns hashref of Code => description
1333 Returns undef if no authorised value category is defined for the kohafield.
1337 sub GetKohaAuthorisedValues
{
1338 my ($kohafield,$fwcode,$opac) = @_;
1339 $fwcode='' unless $fwcode;
1341 my $dbh = C4
::Context
->dbh;
1342 my $avcode = GetAuthValCode
($kohafield,$fwcode);
1344 my $sth = $dbh->prepare("select authorised_value, lib, lib_opac from authorised_values where category=? ");
1345 $sth->execute($avcode);
1346 while ( my ($val, $lib, $lib_opac) = $sth->fetchrow_array ) {
1347 $values{$val} = ($opac && $lib_opac) ?
$lib_opac : $lib;
1355 =head2 GetKohaAuthorisedValuesFromField
1357 Takes $field, $subfield, $fwcode as parameters.
1359 If $opac parameter is set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1360 $subfield can be undefined
1362 Returns hashref of Code => description
1364 Returns undef if no authorised value category is defined for the given field and subfield
1368 sub GetKohaAuthorisedValuesFromField
{
1369 my ($field, $subfield, $fwcode,$opac) = @_;
1370 $fwcode='' unless $fwcode;
1372 my $dbh = C4
::Context
->dbh;
1373 my $avcode = GetAuthValCodeFromField
($field, $subfield, $fwcode);
1375 my $sth = $dbh->prepare("select authorised_value, lib, lib_opac from authorised_values where category=? ");
1376 $sth->execute($avcode);
1377 while ( my ($val, $lib, $lib_opac) = $sth->fetchrow_array ) {
1378 $values{$val} = ($opac && $lib_opac) ?
$lib_opac : $lib;
1386 =head2 GetKohaAuthorisedValuesMapping
1388 Takes a hash as a parameter. The interface key indicates the
1389 description to use in the mapping.
1392 "{kohafield},{frameworkcode},{authorised_value}" => "{description}"
1393 for all the kohafields, frameworkcodes, and authorised values.
1395 Returns undef if nothing is found.
1399 sub GetKohaAuthorisedValuesMapping
{
1400 my ($parameter) = @_;
1401 my $interface = $parameter->{'interface'} // '';
1403 my $query_mapping = q{
1404 SELECT TA.kohafield,TA.authorised_value AS category,
1405 TA.frameworkcode,TB.authorised_value,
1406 IF(TB.lib_opac>'',TB.lib_opac,TB.lib) AS OPAC,
1407 TB.lib AS Intranet,TB.lib_opac
1408 FROM marc_subfield_structure AS TA JOIN
1409 authorised_values as TB ON
1410 TA.authorised_value=TB.category
1411 WHERE TA.kohafield>'' AND TA.authorised_value>'';
1413 my $dbh = C4
::Context
->dbh;
1414 my $sth = $dbh->prepare($query_mapping);
1417 if ($interface eq 'opac') {
1418 while (my $row = $sth->fetchrow_hashref) {
1419 $avmapping->{$row->{kohafield
}.",".$row->{frameworkcode
}.",".$row->{authorised_value
}} = $row->{OPAC
};
1423 while (my $row = $sth->fetchrow_hashref) {
1424 $avmapping->{$row->{kohafield
}.",".$row->{frameworkcode
}.",".$row->{authorised_value
}} = $row->{Intranet
};
1432 my $escaped_string = C4::Koha::xml_escape($string);
1434 Convert &, <, >, ', and " in a string to XML entities
1440 return '' unless defined $str;
1441 $str =~ s/&/&/g;
1444 $str =~ s/'/'/g;
1445 $str =~ s/"/"/g;
1449 =head2 GetKohaAuthorisedValueLib
1451 Takes $category, $authorised_value as parameters.
1453 If $opac parameter is set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1455 Returns authorised value description
1459 sub GetKohaAuthorisedValueLib
{
1460 my ($category,$authorised_value,$opac) = @_;
1462 my $dbh = C4
::Context
->dbh;
1463 my $sth = $dbh->prepare("select lib, lib_opac from authorised_values where category=? and authorised_value=?");
1464 $sth->execute($category,$authorised_value);
1465 my $data = $sth->fetchrow_hashref;
1466 $value = ($opac && $$data{'lib_opac'}) ?
$$data{'lib_opac'} : $$data{'lib'};
1470 =head2 AddAuthorisedValue
1472 AddAuthorisedValue($category, $authorised_value, $lib, $lib_opac, $imageurl);
1474 Create a new authorised value.
1478 sub AddAuthorisedValue
{
1479 my ($category, $authorised_value, $lib, $lib_opac, $imageurl) = @_;
1481 my $dbh = C4
::Context
->dbh;
1483 INSERT INTO authorised_values
(category
, authorised_value
, lib
, lib_opac
, imageurl
)
1486 my $sth = $dbh->prepare($query);
1487 $sth->execute($category, $authorised_value, $lib, $lib_opac, $imageurl);
1490 =head2 display_marc_indicators
1492 my $display_form = C4::Koha::display_marc_indicators($field);
1494 C<$field> is a MARC::Field object
1496 Generate a display form of the indicators of a variable
1497 MARC field, replacing any blanks with '#'.
1501 sub display_marc_indicators
{
1503 my $indicators = '';
1504 if ($field->tag() >= 10) {
1505 $indicators = $field->indicator(1) . $field->indicator(2);
1506 $indicators =~ s/ /#/g;
1511 sub GetNormalizedUPC
{
1512 my ($record,$marcflavour) = @_;
1515 if ($marcflavour eq 'UNIMARC') {
1516 @fields = $record->field('072');
1517 foreach my $field (@fields) {
1518 my $upc = _normalize_match_point
($field->subfield('a'));
1525 else { # assume marc21 if not unimarc
1526 @fields = $record->field('024');
1527 foreach my $field (@fields) {
1528 my $indicator = $field->indicator(1);
1529 my $upc = _normalize_match_point
($field->subfield('a'));
1530 if ($indicator == 1 and $upc ne '') {
1537 # Normalizes and returns the first valid ISBN found in the record
1538 # ISBN13 are converted into ISBN10. This is required to get some book cover images.
1539 sub GetNormalizedISBN
{
1540 my ($isbn,$record,$marcflavour) = @_;
1543 # Koha attempts to store multiple ISBNs in biblioitems.isbn, separated by " | "
1544 # anything after " | " should be removed, along with the delimiter
1545 ($isbn) = split(/\|/, $isbn );
1546 return _isbn_cleanup
($isbn);
1548 return unless $record;
1550 if ($marcflavour eq 'UNIMARC') {
1551 @fields = $record->field('010');
1552 foreach my $field (@fields) {
1553 my $isbn = $field->subfield('a');
1555 return _isbn_cleanup
($isbn);
1561 else { # assume marc21 if not unimarc
1562 @fields = $record->field('020');
1563 foreach my $field (@fields) {
1564 $isbn = $field->subfield('a');
1566 return _isbn_cleanup
($isbn);
1574 sub GetNormalizedEAN
{
1575 my ($record,$marcflavour) = @_;
1578 if ($marcflavour eq 'UNIMARC') {
1579 @fields = $record->field('073');
1580 foreach my $field (@fields) {
1581 $ean = _normalize_match_point
($field->subfield('a'));
1587 else { # assume marc21 if not unimarc
1588 @fields = $record->field('024');
1589 foreach my $field (@fields) {
1590 my $indicator = $field->indicator(1);
1591 $ean = _normalize_match_point
($field->subfield('a'));
1592 if ($indicator == 3 and $ean ne '') {
1598 sub GetNormalizedOCLCNumber
{
1599 my ($record,$marcflavour) = @_;
1602 if ($marcflavour eq 'UNIMARC') {
1603 # TODO: add UNIMARC fields
1605 else { # assume marc21 if not unimarc
1606 @fields = $record->field('035');
1607 foreach my $field (@fields) {
1608 $oclc = $field->subfield('a');
1609 if ($oclc =~ /OCoLC/) {
1610 $oclc =~ s/\(OCoLC\)//;
1619 sub GetAuthvalueDropbox
{
1620 my ( $authcat, $default ) = @_;
1621 my $branch_limit = C4
::Context
->userenv ? C4
::Context
->userenv->{"branch"} : "";
1622 my $dbh = C4
::Context
->dbh;
1626 FROM authorised_values
1629 LEFT JOIN authorised_values_branches ON
( id
= av_id
)
1634 $query .= " AND ( branchcode = ? OR branchcode IS NULL )" if $branch_limit;
1635 $query .= " GROUP BY lib ORDER BY category, lib, lib_opac";
1636 my $sth = $dbh->prepare($query);
1637 $sth->execute( $authcat, $branch_limit ?
$branch_limit : () );
1640 my $option_list = [];
1641 my @authorised_values = ( q{} );
1642 while (my $av = $sth->fetchrow_hashref) {
1643 push @
{$option_list}, {
1644 value
=> $av->{authorised_value
},
1645 label
=> $av->{lib
},
1646 default => ($default eq $av->{authorised_value
}),
1650 if ( @
{$option_list} ) {
1651 return $option_list;
1657 =head2 GetDailyQuote($opts)
1659 Takes a hashref of options
1661 Currently supported options are:
1663 'id' An exact quote id
1664 'random' Select a random quote
1665 noop When no option is passed in, this sub will return the quote timestamped for the current day
1667 The function returns an anonymous hash following this format:
1670 'source' => 'source-of-quote',
1671 'timestamp' => 'timestamp-value',
1672 'text' => 'text-of-quote',
1678 # This is definitely a candidate for some sort of caching once we finally settle caching/persistence issues...
1679 # at least for default option
1683 my $dbh = C4
::Context
->dbh;
1688 $query = 'SELECT * FROM quotes WHERE id = ?';
1689 $sth = $dbh->prepare($query);
1690 $sth->execute($opts{'id'});
1691 $quote = $sth->fetchrow_hashref();
1693 elsif ($opts{'random'}) {
1694 # Fall through... we also return a random quote as a catch-all if all else fails
1697 $query = 'SELECT * FROM quotes WHERE timestamp LIKE CONCAT(CURRENT_DATE,\'%\') ORDER BY timestamp DESC LIMIT 0,1';
1698 $sth = $dbh->prepare($query);
1700 $quote = $sth->fetchrow_hashref();
1702 unless ($quote) { # if there are not matches, choose a random quote
1703 # get a list of all available quote ids
1704 $sth = C4
::Context
->dbh->prepare('SELECT count(*) FROM quotes;');
1706 my $range = ($sth->fetchrow_array)[0];
1707 # chose a random id within that range if there is more than one quote
1708 my $offset = int(rand($range));
1710 $query = 'SELECT * FROM quotes ORDER BY id LIMIT 1 OFFSET ?';
1711 $sth = C4
::Context
->dbh->prepare($query);
1712 # see http://www.perlmonks.org/?node_id=837422 for why
1713 # we're being verbose and using bind_param
1714 $sth->bind_param(1, $offset, SQL_INTEGER
);
1716 $quote = $sth->fetchrow_hashref();
1717 # update the timestamp for that quote
1718 $query = 'UPDATE quotes SET timestamp = ? WHERE id = ?';
1719 $sth = C4
::Context
->dbh->prepare($query);
1721 DateTime
::Format
::MySQL
->format_datetime( dt_from_string
() ),
1728 sub _normalize_match_point
{
1729 my $match_point = shift;
1730 (my $normalized_match_point) = $match_point =~ /([\d-]*[X]*)/;
1731 $normalized_match_point =~ s/-//g;
1733 return $normalized_match_point;
1738 return NormalizeISBN
(
1741 format
=> 'ISBN-10',
1747 =head2 NormalizedISBN
1749 my $isbns = NormalizedISBN({
1751 strip_hyphens => [0,1],
1752 format => ['ISBN-10', 'ISBN-13']
1755 Returns an isbn validated by Business::ISBN.
1756 Optionally strips hyphens and/or forces the isbn
1757 to be of the specified format.
1759 If the string cannot be validated as an isbn,
1767 my $string = $params->{isbn
};
1768 my $strip_hyphens = $params->{strip_hyphens
};
1769 my $format = $params->{format
};
1771 return unless $string;
1773 my $isbn = Business
::ISBN
->new($string);
1775 if ( $isbn && $isbn->is_valid() ) {
1777 if ( $format eq 'ISBN-10' ) {
1778 $isbn = $isbn->as_isbn10();
1780 elsif ( $format eq 'ISBN-13' ) {
1781 $isbn = $isbn->as_isbn13();
1783 return unless $isbn;
1785 if ($strip_hyphens) {
1786 $string = $isbn->as_string( [] );
1788 $string = $isbn->as_string();
1795 =head2 GetVariationsOfISBN
1797 my @isbns = GetVariationsOfISBN( $isbn );
1799 Returns a list of variations of the given isbn in
1800 both ISBN-10 and ISBN-13 formats, with and without
1803 In a scalar context, the isbns are returned as a
1804 string delimited by ' | '.
1808 sub GetVariationsOfISBN
{
1811 return unless $isbn;
1815 push( @isbns, NormalizeISBN
({ isbn
=> $isbn }) );
1816 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-10' }) );
1817 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-13' }) );
1818 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-10', strip_hyphens
=> 1 }) );
1819 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-13', strip_hyphens
=> 1 }) );
1821 # Strip out any "empty" strings from the array
1822 @isbns = grep { defined($_) && $_ =~ /\S/ } @isbns;
1824 return wantarray ?
@isbns : join( " | ", @isbns );
1827 =head2 GetVariationsOfISBNs
1829 my @isbns = GetVariationsOfISBNs( @isbns );
1831 Returns a list of variations of the given isbns in
1832 both ISBN-10 and ISBN-13 formats, with and without
1835 In a scalar context, the isbns are returned as a
1836 string delimited by ' | '.
1840 sub GetVariationsOfISBNs
{
1843 @isbns = map { GetVariationsOfISBN
( $_ ) } @isbns;
1845 return wantarray ?
@isbns : join( " | ", @isbns );
1848 =head2 IsKohaFieldLinked
1850 my $is_linked = IsKohaFieldLinked({
1851 kohafield => $kohafield,
1852 frameworkcode => $frameworkcode,
1855 Return 1 if the field is linked
1859 sub IsKohaFieldLinked
{
1860 my ( $params ) = @_;
1861 my $kohafield = $params->{kohafield
};
1862 my $frameworkcode = $params->{frameworkcode
} || '';
1863 my $dbh = C4
::Context
->dbh;
1864 my $is_linked = $dbh->selectcol_arrayref( q
|
1866 FROM marc_subfield_structure
1867 WHERE frameworkcode
= ?
1869 |,{}, $frameworkcode, $kohafield );
1870 return $is_linked->[0];