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
28 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);
34 use vars
qw(@ISA @EXPORT @EXPORT_OK $DEBUG);
40 &GetPrinters &GetPrinter
41 &GetItemTypes &getitemtypeinfo
42 &GetItemTypesCategorized &GetItemTypesByCategory
43 &GetSupportName &GetSupportList
44 &getframeworks &getframeworkinfo
50 &get_notforloan_label_of
53 &getitemtypeimagelocation
55 &GetAuthorisedValueCategories
56 &GetKohaAuthorisedValues
57 &GetKohaAuthorisedValuesFromField
58 &GetKohaAuthorisedValuesMapping
59 &GetKohaAuthorisedValueLib
60 &GetAuthorisedValueByCode
65 &GetNormalizedOCLCNumber
75 @EXPORT_OK = qw( GetDailyQuote );
80 C4::Koha - Perl Module containing convenience functions for Koha scripts
88 Koha.pm provides many functions for Koha scripts.
96 $itemtypename = &GetSupportName($codestring);
98 Returns a string with the name of the itemtype.
104 return if (! $codestring);
106 my $advanced_search_types = C4
::Context
->preference("AdvancedSearchTypes");
107 if (!$advanced_search_types or $advanced_search_types eq 'itemtypes') {
114 my $sth = C4
::Context
->dbh->prepare($query);
115 $sth->execute($codestring);
116 ($resultstring)=$sth->fetchrow;
117 return $resultstring;
120 C4
::Context
->dbh->prepare(
121 "SELECT lib FROM authorised_values WHERE category = ? AND authorised_value = ?"
123 $sth->execute( $advanced_search_types, $codestring );
124 my $data = $sth->fetchrow_hashref;
125 return $$data{'lib'};
129 =head2 GetSupportList
131 $itemtypes = &GetSupportList();
133 Returns an array ref containing informations about Support (since itemtype is rather a circulation code when item-level-itypes is used).
135 build a HTML select with the following code :
137 =head3 in PERL SCRIPT
139 my $itemtypes = GetSupportList();
140 $template->param(itemtypeloop => $itemtypes);
144 <select name="itemtype" id="itemtype">
145 <option value=""></option>
146 [% FOREACH itemtypeloo IN itemtypeloop %]
147 [% IF ( itemtypeloo.selected ) %]
148 <option value="[% itemtypeloo.itemtype %]" selected="selected">[% itemtypeloo.description %]</option>
150 <option value="[% itemtypeloo.itemtype %]">[% itemtypeloo.description %]</option>
158 my $advanced_search_types = C4
::Context
->preference("AdvancedSearchTypes");
159 if (!$advanced_search_types or $advanced_search_types =~ /itemtypes/) {
160 return GetItemTypes
( style
=> 'array' );
162 my $advsearchtypes = GetAuthorisedValues
($advanced_search_types);
163 my @results= map {{itemtype
=>$$_{authorised_value
},description
=>$$_{lib
},imageurl
=>$$_{imageurl
}}} @
$advsearchtypes;
169 $itemtypes = &GetItemTypes( style => $style );
171 Returns information about existing itemtypes.
174 style: either 'array' or 'hash', defaults to 'hash'.
175 'array' returns an arrayref,
176 'hash' return a hashref with the itemtype value as the key
178 build a HTML select with the following code :
180 =head3 in PERL SCRIPT
182 my $itemtypes = GetItemTypes;
184 foreach my $thisitemtype (sort keys %$itemtypes) {
185 my $selected = 1 if $thisitemtype eq $itemtype;
186 my %row =(value => $thisitemtype,
187 selected => $selected,
188 description => $itemtypes->{$thisitemtype}->{'description'},
190 push @itemtypesloop, \%row;
192 $template->param(itemtypeloop => \@itemtypesloop);
196 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
197 <select name="itemtype">
198 <option value="">Default</option>
199 <!-- TMPL_LOOP name="itemtypeloop" -->
200 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="description" --></option>
203 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
204 <input type="submit" value="OK" class="button">
211 my $style = defined( $params{'style'} ) ?
$params{'style'} : 'hash';
213 require C4
::Languages
;
214 my $language = C4
::Languages
::getlanguage
();
215 # returns a reference to a hash of references to itemtypes...
216 my $dbh = C4
::Context
->dbh;
220 itemtypes
.description
,
221 itemtypes
.rentalcharge
,
222 itemtypes
.notforloan
,
225 itemtypes
.checkinmsg
,
226 itemtypes
.checkinmsgtype
,
227 itemtypes
.sip_media_type
,
228 itemtypes
.hideinopac
,
229 itemtypes
.searchcategory
,
230 COALESCE
( localization
.translation
, itemtypes
.description
) AS translated_description
232 LEFT JOIN localization ON itemtypes
.itemtype
= localization
.code
233 AND localization
.entity
= 'itemtypes'
234 AND localization
.lang
= ?
237 my $sth = $dbh->prepare($query);
238 $sth->execute( $language );
240 if ( $style eq 'hash' ) {
242 while ( my $IT = $sth->fetchrow_hashref ) {
243 $itemtypes{ $IT->{'itemtype'} } = $IT;
245 return ( \
%itemtypes );
247 return [ sort { lc $a->{translated_description
} cmp lc $b->{translated_description
} } @
{ $sth->fetchall_arrayref( {} ) } ];
251 =head2 GetItemTypesCategorized
253 $categories = GetItemTypesCategorized();
255 Returns a hashref containing search categories.
256 A search category will be put in the hash if at least one of its itemtypes is visible in OPAC.
257 The categories must be part of Authorized Values (ITEMTYPECAT)
261 sub GetItemTypesCategorized
{
262 my $dbh = C4
::Context
->dbh;
263 # Order is important, so that partially hidden (some items are not visible in OPAC) search
264 # categories will be visible. hideinopac=0 must be last.
266 SELECT itemtype
, description
, imageurl
, hideinopac
, 0 as
'iscat' FROM itemtypes WHERE ISNULL
(searchcategory
) or length(searchcategory
) = 0
268 SELECT DISTINCT searchcategory AS
`itemtype`,
269 authorised_values
.lib_opac AS description
,
270 authorised_values
.imageurl AS imageurl
,
271 hideinopac
, 1 as
'iscat'
273 LEFT JOIN authorised_values ON searchcategory
= authorised_value
274 WHERE searchcategory
> '' and hideinopac
=1
276 SELECT DISTINCT searchcategory AS
`itemtype`,
277 authorised_values
.lib_opac AS description
,
278 authorised_values
.imageurl AS imageurl
,
279 hideinopac
, 1 as
'iscat'
281 LEFT JOIN authorised_values ON searchcategory
= authorised_value
282 WHERE searchcategory
> '' and hideinopac
=0
284 return ($dbh->selectall_hashref($query,'itemtype'));
287 =head2 GetItemTypesByCategory
289 @results = GetItemTypesByCategory( $searchcategory );
291 Returns the itemtype code of all itemtypes included in a searchcategory.
295 sub GetItemTypesByCategory
{
299 my $dbh = C4
::Context
->dbh;
300 my $query = qq|SELECT itemtype FROM itemtypes WHERE searchcategory
=?
|;
301 my $tmp=$dbh->selectcol_arrayref($query,undef,$category);
307 $frameworks = &getframework();
309 Returns information about existing frameworks
311 build a HTML select with the following code :
313 =head3 in PERL SCRIPT
315 my $frameworks = getframeworks();
317 foreach my $thisframework (keys %$frameworks) {
318 my $selected = 1 if $thisframework eq $frameworkcode;
320 value => $thisframework,
321 selected => $selected,
322 description => $frameworks->{$thisframework}->{'frameworktext'},
324 push @frameworksloop, \%row;
326 $template->param(frameworkloop => \@frameworksloop);
330 <form action="[% script_name %] method=post>
331 <select name="frameworkcode">
332 <option value="">Default</option>
333 [% FOREACH framework IN frameworkloop %]
334 [% IF ( framework.selected ) %]
335 <option value="[% framework.value %]" selected="selected">[% framework.description %]</option>
337 <option value="[% framework.value %]">[% framework.description %]</option>
341 <input type=text name=searchfield value="[% searchfield %]">
342 <input type="submit" value="OK" class="button">
349 # returns a reference to a hash of references to branches...
351 my $dbh = C4
::Context
->dbh;
352 my $sth = $dbh->prepare("select * from biblio_framework");
354 while ( my $IT = $sth->fetchrow_hashref ) {
355 $itemtypes{ $IT->{'frameworkcode'} } = $IT;
357 return ( \
%itemtypes );
360 =head2 GetFrameworksLoop
362 $frameworks = GetFrameworksLoop( $frameworkcode );
364 Returns the loop suggested on getframework(), but ordered by framework description.
366 build a HTML select with the following code :
368 =head3 in PERL SCRIPT
370 $template->param( frameworkloop => GetFrameworksLoop( $frameworkcode ) );
374 Same as getframework()
376 <form action="[% script_name %] method=post>
377 <select name="frameworkcode">
378 <option value="">Default</option>
379 [% FOREACH framework IN frameworkloop %]
380 [% IF ( framework.selected ) %]
381 <option value="[% framework.value %]" selected="selected">[% framework.description %]</option>
383 <option value="[% framework.value %]">[% framework.description %]</option>
387 <input type=text name=searchfield value="[% searchfield %]">
388 <input type="submit" value="OK" class="button">
393 sub GetFrameworksLoop
{
394 my $frameworkcode = shift;
395 my $frameworks = getframeworks
();
397 foreach my $thisframework (sort { uc($frameworks->{$a}->{'frameworktext'}) cmp uc($frameworks->{$b}->{'frameworktext'}) } keys %$frameworks) {
398 my $selected = ( $thisframework eq $frameworkcode ) ?
1 : undef;
400 value
=> $thisframework,
401 selected
=> $selected,
402 description
=> $frameworks->{$thisframework}->{'frameworktext'},
404 push @frameworkloop, \
%row;
406 return \
@frameworkloop;
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 require C4
::Languages
;
441 my $language = C4
::Languages
::getlanguage
();
442 my $it = $dbh->selectrow_hashref(q
|
445 itemtypes
.description
,
446 itemtypes
.rentalcharge
,
447 itemtypes
.notforloan
,
450 itemtypes
.checkinmsg
,
451 itemtypes
.checkinmsgtype
,
452 itemtypes
.sip_media_type
,
453 COALESCE
( localization
.translation
, itemtypes
.description
) AS translated_description
455 LEFT JOIN localization ON itemtypes
.itemtype
= localization
.code
456 AND localization
.entity
= 'itemtypes'
457 AND localization
.lang
= ?
458 WHERE itemtypes
.itemtype
= ?
459 |, undef, $language, $itemtype );
461 $it->{imageurl
} = getitemtypeimagelocation
( ( ( defined $interface && $interface eq 'opac' ) ?
'opac' : 'intranet' ), $it->{imageurl
} );
466 =head2 getitemtypeimagedir
468 my $directory = getitemtypeimagedir( 'opac' );
470 pass in 'opac' or 'intranet'. Defaults to 'opac'.
472 returns the full path to the appropriate directory containing images.
476 sub getitemtypeimagedir
{
477 my $src = shift || 'opac';
478 if ($src eq 'intranet') {
479 return C4
::Context
->config('intrahtdocs') . '/' .C4
::Context
->preference('template') . '/img/itemtypeimg';
481 return C4
::Context
->config('opachtdocs') . '/' . C4
::Context
->preference('opacthemes') . '/itemtypeimg';
485 sub getitemtypeimagesrc
{
486 my $src = shift || 'opac';
487 if ($src eq 'intranet') {
488 return '/intranet-tmpl' . '/' . C4
::Context
->preference('template') . '/img/itemtypeimg';
490 return '/opac-tmpl' . '/' . C4
::Context
->preference('opacthemes') . '/itemtypeimg';
494 sub getitemtypeimagelocation
{
495 my ( $src, $image ) = @_;
497 return '' if ( !$image );
500 my $scheme = ( URI
::Split
::uri_split
( $image ) )[0];
502 return $image if ( $scheme );
504 return getitemtypeimagesrc
( $src ) . '/' . $image;
507 =head3 _getImagesFromDirectory
509 Find all of the image files in a directory in the filesystem
511 parameters: a directory name
513 returns: a list of images in that directory.
515 Notes: this does not traverse into subdirectories. See
516 _getSubdirectoryNames for help with that.
517 Images are assumed to be files with .gif or .png file extensions.
518 The image names returned do not have the directory name on them.
522 sub _getImagesFromDirectory
{
523 my $directoryname = shift;
524 return unless defined $directoryname;
525 return unless -d
$directoryname;
527 if ( opendir ( my $dh, $directoryname ) ) {
528 my @images = grep { /\.(gif|png)$/i } readdir( $dh );
530 @images = sort(@images);
533 warn "unable to opendir $directoryname: $!";
538 =head3 _getSubdirectoryNames
540 Find all of the directories in a directory in the filesystem
542 parameters: a directory name
544 returns: a list of subdirectories in that directory.
546 Notes: this does not traverse into subdirectories. Only the first
547 level of subdirectories are returned.
548 The directory names returned don't have the parent directory name on them.
552 sub _getSubdirectoryNames
{
553 my $directoryname = shift;
554 return unless defined $directoryname;
555 return unless -d
$directoryname;
557 if ( opendir ( my $dh, $directoryname ) ) {
558 my @directories = grep { -d File
::Spec
->catfile( $directoryname, $_ ) && ! ( /^\./ ) } readdir( $dh );
562 warn "unable to opendir $directoryname: $!";
569 returns: a listref of hashrefs. Each hash represents another collection of images.
571 { imagesetname => 'npl', # the name of the image set (npl is the original one)
572 images => listref of image hashrefs
575 each image is represented by a hashref like this:
577 { KohaImage => 'npl/image.gif',
578 StaffImageUrl => '/intranet-tmpl/prog/img/itemtypeimg/npl/image.gif',
579 OpacImageURL => '/opac-tmpl/prog/itemtypeimg/npl/image.gif'
580 checked => 0 or 1: was this the image passed to this method?
581 Note: I'd like to remove this somehow.
588 my $checked = $params{'checked'} || '';
590 my $paths = { staff
=> { filesystem
=> getitemtypeimagedir
('intranet'),
591 url
=> getitemtypeimagesrc
('intranet'),
593 opac
=> { filesystem
=> getitemtypeimagedir
('opac'),
594 url
=> getitemtypeimagesrc
('opac'),
598 my @imagesets = (); # list of hasrefs of image set data to pass to template
599 my @subdirectories = _getSubdirectoryNames
( $paths->{'staff'}{'filesystem'} );
600 foreach my $imagesubdir ( @subdirectories ) {
601 warn $imagesubdir if $DEBUG;
602 my @imagelist = (); # hashrefs of image info
603 my @imagenames = _getImagesFromDirectory
( File
::Spec
->catfile( $paths->{'staff'}{'filesystem'}, $imagesubdir ) );
604 my $imagesetactive = 0;
605 foreach my $thisimage ( @imagenames ) {
607 { KohaImage
=> "$imagesubdir/$thisimage",
608 StaffImageUrl
=> join( '/', $paths->{'staff'}{'url'}, $imagesubdir, $thisimage ),
609 OpacImageUrl
=> join( '/', $paths->{'opac'}{'url'}, $imagesubdir, $thisimage ),
610 checked
=> "$imagesubdir/$thisimage" eq $checked ?
1 : 0,
613 $imagesetactive = 1 if "$imagesubdir/$thisimage" eq $checked;
615 push @imagesets, { imagesetname
=> $imagesubdir,
616 imagesetactive
=> $imagesetactive,
617 images
=> \
@imagelist };
625 $printers = &GetPrinters();
626 @queues = keys %$printers;
628 Returns information about existing printer queues.
630 C<$printers> is a reference-to-hash whose keys are the print queues
631 defined in the printers table of the Koha database. The values are
632 references-to-hash, whose keys are the fields in the printers table.
638 my $dbh = C4
::Context
->dbh;
639 my $sth = $dbh->prepare("select * from printers");
641 while ( my $printer = $sth->fetchrow_hashref ) {
642 $printers{ $printer->{'printqueue'} } = $printer;
644 return ( \
%printers );
649 $printer = GetPrinter( $query, $printers );
654 my ( $query, $printers ) = @_; # get printer for this query from printers
655 my $printer = $query->param('printer');
656 my %cookie = $query->cookie('userenv');
657 ($printer) || ( $printer = $cookie{'printer'} ) || ( $printer = '' );
658 ( $printers->{$printer} ) || ( $printer = ( keys %$printers )[0] );
664 Returns the number of pages to display in a pagination bar, given the number
665 of items and the number of items per page.
670 my ( $nb_items, $nb_items_per_page ) = @_;
672 return int( ( $nb_items - 1 ) / $nb_items_per_page ) + 1;
677 (@themes) = &getallthemes('opac');
678 (@themes) = &getallthemes('intranet');
680 Returns an array of all available themes.
688 if ( $type eq 'intranet' ) {
689 $htdocs = C4
::Context
->config('intrahtdocs');
692 $htdocs = C4
::Context
->config('opachtdocs');
694 opendir D
, "$htdocs";
695 my @dirlist = readdir D
;
696 foreach my $directory (@dirlist) {
697 next if $directory eq 'lib';
698 -d
"$htdocs/$directory/en" and push @themes, $directory;
705 if ( C4
::Context
->preference("marcflavour") eq "UNIMARC" ) {
710 tags
=> [ qw
/ 600ab 601ab 602a 604at 605a 606ax 610a / ],
716 tags
=> [ qw
/ 607a / ],
722 tags
=> [ qw
/ 500a 501a 503a / ],
728 tags
=> [ qw
/ 700ab 701ab 702ab / ],
729 sep
=> C4
::Context
->preference("UNIMARCAuthorsFacetsSeparator"),
734 tags
=> [ qw
/ 225a / ],
740 tags
=> [ qw
/ 995e / ],
744 unless ( Koha
::Libraries
->search->count == 1 )
746 my $DisplayLibraryFacets = C4
::Context
->preference('DisplayLibraryFacets');
747 if ( $DisplayLibraryFacets eq 'both'
748 || $DisplayLibraryFacets eq 'holding' )
753 idx
=> 'holdingbranch',
754 label
=> 'HoldingLibrary',
755 tags
=> [qw
/ 995c /],
760 if ( $DisplayLibraryFacets eq 'both'
761 || $DisplayLibraryFacets eq 'home' )
767 label
=> 'HomeLibrary',
768 tags
=> [qw
/ 995b /],
779 tags
=> [ qw
/ 650a / ],
784 # label => 'People and Organizations',
785 # tags => [ qw/ 600a 610a 611a / ],
791 tags
=> [ qw
/ 651a / ],
797 tags
=> [ qw
/ 630a / ],
803 tags
=> [ qw
/ 100a 110a 700a / ],
809 tags
=> [ qw
/ 440a 490a / ],
814 label
=> 'ItemTypes',
815 tags
=> [ qw
/ 952y 942c / ],
821 tags
=> [ qw
/ 952c / ],
825 unless ( Koha
::Libraries
->search->count == 1 )
827 my $DisplayLibraryFacets = C4
::Context
->preference('DisplayLibraryFacets');
828 if ( $DisplayLibraryFacets eq 'both'
829 || $DisplayLibraryFacets eq 'holding' )
834 idx
=> 'holdingbranch',
835 label
=> 'HoldingLibrary',
836 tags
=> [qw
/ 952b /],
841 if ( $DisplayLibraryFacets eq 'both'
842 || $DisplayLibraryFacets eq 'home' )
848 label
=> 'HomeLibrary',
849 tags
=> [qw
/ 952a /],
860 Return a href where a key is associated to a href. You give a query,
861 the name of the key among the fields returned by the query. If you
862 also give as third argument the name of the value, the function
863 returns a href of scalar. The optional 4th argument is an arrayref of
864 items passed to the C<execute()> call. It is designed to bind
865 parameters to any placeholders in your SQL.
874 # generic href of any information on the item, href of href.
875 my $iteminfos_of = get_infos_of($query, 'itemnumber');
876 print $iteminfos_of->{$itemnumber}{barcode};
878 # specific information, href of scalar
879 my $barcode_of_item = get_infos_of($query, 'itemnumber', 'barcode');
880 print $barcode_of_item->{$itemnumber};
885 my ( $query, $key_name, $value_name, $bind_params ) = @_;
887 my $dbh = C4
::Context
->dbh;
889 my $sth = $dbh->prepare($query);
890 $sth->execute( @
$bind_params );
893 while ( my $row = $sth->fetchrow_hashref ) {
894 if ( defined $value_name ) {
895 $infos_of{ $row->{$key_name} } = $row->{$value_name};
898 $infos_of{ $row->{$key_name} } = $row;
906 =head2 get_notforloan_label_of
908 my $notforloan_label_of = get_notforloan_label_of();
910 Each authorised value of notforloan (information available in items and
911 itemtypes) is link to a single label.
913 Returns a href where keys are authorised values and values are corresponding
916 foreach my $authorised_value (keys %{$notforloan_label_of}) {
918 "authorised_value: %s => %s\n",
920 $notforloan_label_of->{$authorised_value}
926 # FIXME - why not use GetAuthorisedValues ??
928 sub get_notforloan_label_of
{
929 my $dbh = C4
::Context
->dbh;
932 SELECT authorised_value
933 FROM marc_subfield_structure
934 WHERE kohafield = \'items.notforloan\'
937 my $sth = $dbh->prepare($query);
939 my ($statuscode) = $sth->fetchrow_array();
944 FROM authorised_values
947 $sth = $dbh->prepare($query);
948 $sth->execute($statuscode);
949 my %notforloan_label_of;
950 while ( my $row = $sth->fetchrow_hashref ) {
951 $notforloan_label_of{ $row->{authorised_value
} } = $row->{lib
};
955 return \
%notforloan_label_of;
958 =head2 GetAuthValCode
960 $authvalcode = GetAuthValCode($kohafield,$frameworkcode);
965 my ($kohafield,$fwcode) = @_;
966 my $dbh = C4
::Context
->dbh;
967 $fwcode='' unless $fwcode;
968 my $sth = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield=? and frameworkcode=?');
969 $sth->execute($kohafield,$fwcode);
970 my ($authvalcode) = $sth->fetchrow_array;
974 =head2 GetAuthValCodeFromField
976 $authvalcode = GetAuthValCodeFromField($field,$subfield,$frameworkcode);
978 C<$subfield> can be undefined
982 sub GetAuthValCodeFromField
{
983 my ($field,$subfield,$fwcode) = @_;
984 my $dbh = C4
::Context
->dbh;
985 $fwcode='' unless $fwcode;
987 if (defined $subfield) {
988 $sth = $dbh->prepare('select authorised_value from marc_subfield_structure where tagfield=? and tagsubfield=? and frameworkcode=?');
989 $sth->execute($field,$subfield,$fwcode);
991 $sth = $dbh->prepare('select authorised_value from marc_tag_structure where tagfield=? and frameworkcode=?');
992 $sth->execute($field,$fwcode);
994 my ($authvalcode) = $sth->fetchrow_array;
998 =head2 GetAuthorisedValues
1000 $authvalues = GetAuthorisedValues([$category]);
1002 This function returns all authorised values from the'authorised_value' table in a reference to array of hashrefs.
1004 C<$category> returns authorised values for just one category (optional).
1006 C<$opac> If set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1010 sub GetAuthorisedValues
{
1011 my ( $category, $opac ) = @_;
1013 # Is this cached already?
1014 $opac = $opac ?
1 : 0; # normalise to be safe
1016 C4
::Context
->userenv ? C4
::Context
->userenv->{"branch"} : "";
1018 "AuthorisedValues-$category-$opac-$branch_limit";
1019 my $cache = Koha
::Caches
->get_instance();
1020 my $result = $cache->get_from_cache($cache_key);
1021 return $result if $result;
1024 my $dbh = C4
::Context
->dbh;
1026 SELECT DISTINCT av
.*
1027 FROM authorised_values av
1030 LEFT JOIN authorised_values_branches ON
( id
= av_id
)
1035 push @where_strings, "category = ?";
1036 push @where_args, $category;
1039 push @where_strings, "( branchcode = ? OR branchcode IS NULL )";
1040 push @where_args, $branch_limit;
1042 if(@where_strings > 0) {
1043 $query .= " WHERE " . join(" AND ", @where_strings);
1045 $query .= ' ORDER BY category, ' . (
1046 $opac ?
'COALESCE(lib_opac, lib)'
1050 my $sth = $dbh->prepare($query);
1052 $sth->execute( @where_args );
1053 while (my $data=$sth->fetchrow_hashref) {
1054 if ($opac && $data->{lib_opac
}) {
1055 $data->{lib
} = $data->{lib_opac
};
1057 push @results, $data;
1061 $cache->set_in_cache( $cache_key, \
@results, { deepcopy
=> 1, expiry
=> 5 } );
1065 =head2 GetAuthorisedValueCategories
1067 $auth_categories = GetAuthorisedValueCategories();
1069 Return an arrayref of all of the available authorised
1074 sub GetAuthorisedValueCategories
{
1075 my $dbh = C4
::Context
->dbh;
1076 my $sth = $dbh->prepare("SELECT DISTINCT category FROM authorised_values ORDER BY category");
1079 while (defined (my $category = $sth->fetchrow_array) ) {
1080 push @results, $category;
1085 =head2 GetAuthorisedValueByCode
1087 $authorised_value = GetAuthorisedValueByCode( $category, $authvalcode, $opac );
1089 Return the lib attribute from authorised_values from the row identified
1090 by the passed category and code
1094 sub GetAuthorisedValueByCode
{
1095 my ( $category, $authvalcode, $opac ) = @_;
1097 my $field = $opac ?
'lib_opac' : 'lib';
1098 my $dbh = C4
::Context
->dbh;
1099 my $sth = $dbh->prepare("SELECT $field FROM authorised_values WHERE category=? AND authorised_value =?");
1100 $sth->execute( $category, $authvalcode );
1101 while ( my $data = $sth->fetchrow_hashref ) {
1102 return $data->{ $field };
1106 =head2 GetKohaAuthorisedValues
1108 Takes $kohafield, $fwcode as parameters.
1110 If $opac parameter is set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1112 Returns hashref of Code => description
1114 Returns undef if no authorised value category is defined for the kohafield.
1118 sub GetKohaAuthorisedValues
{
1119 my ($kohafield,$fwcode,$opac) = @_;
1120 $fwcode='' unless $fwcode;
1122 my $dbh = C4
::Context
->dbh;
1123 my $avcode = GetAuthValCode
($kohafield,$fwcode);
1125 my $sth = $dbh->prepare("select authorised_value, lib, lib_opac from authorised_values where category=? ");
1126 $sth->execute($avcode);
1127 while ( my ($val, $lib, $lib_opac) = $sth->fetchrow_array ) {
1128 $values{$val} = ($opac && $lib_opac) ?
$lib_opac : $lib;
1136 =head2 GetKohaAuthorisedValuesFromField
1138 Takes $field, $subfield, $fwcode as parameters.
1140 If $opac parameter is set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1141 $subfield can be undefined
1143 Returns hashref of Code => description
1145 Returns undef if no authorised value category is defined for the given field and subfield
1149 sub GetKohaAuthorisedValuesFromField
{
1150 my ($field, $subfield, $fwcode,$opac) = @_;
1151 $fwcode='' unless $fwcode;
1153 my $dbh = C4
::Context
->dbh;
1154 my $avcode = GetAuthValCodeFromField
($field, $subfield, $fwcode);
1156 my $sth = $dbh->prepare("select authorised_value, lib, lib_opac from authorised_values where category=? ");
1157 $sth->execute($avcode);
1158 while ( my ($val, $lib, $lib_opac) = $sth->fetchrow_array ) {
1159 $values{$val} = ($opac && $lib_opac) ?
$lib_opac : $lib;
1167 =head2 GetKohaAuthorisedValuesMapping
1169 Takes a hash as a parameter. The interface key indicates the
1170 description to use in the mapping.
1173 "{kohafield},{frameworkcode},{authorised_value}" => "{description}"
1174 for all the kohafields, frameworkcodes, and authorised values.
1176 Returns undef if nothing is found.
1180 sub GetKohaAuthorisedValuesMapping
{
1181 my ($parameter) = @_;
1182 my $interface = $parameter->{'interface'} // '';
1184 my $query_mapping = q{
1185 SELECT TA.kohafield,TA.authorised_value AS category,
1186 TA.frameworkcode,TB.authorised_value,
1187 IF(TB.lib_opac>'',TB.lib_opac,TB.lib) AS OPAC,
1188 TB.lib AS Intranet,TB.lib_opac
1189 FROM marc_subfield_structure AS TA JOIN
1190 authorised_values as TB ON
1191 TA.authorised_value=TB.category
1192 WHERE TA.kohafield>'' AND TA.authorised_value>'';
1194 my $dbh = C4
::Context
->dbh;
1195 my $sth = $dbh->prepare($query_mapping);
1198 if ($interface eq 'opac') {
1199 while (my $row = $sth->fetchrow_hashref) {
1200 $avmapping->{$row->{kohafield
}.",".$row->{frameworkcode
}.",".$row->{authorised_value
}} = $row->{OPAC
};
1204 while (my $row = $sth->fetchrow_hashref) {
1205 $avmapping->{$row->{kohafield
}.",".$row->{frameworkcode
}.",".$row->{authorised_value
}} = $row->{Intranet
};
1213 my $escaped_string = C4::Koha::xml_escape($string);
1215 Convert &, <, >, ', and " in a string to XML entities
1221 return '' unless defined $str;
1222 $str =~ s/&/&/g;
1225 $str =~ s/'/'/g;
1226 $str =~ s/"/"/g;
1230 =head2 GetKohaAuthorisedValueLib
1232 Takes $category, $authorised_value as parameters.
1234 If $opac parameter is set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1236 Returns authorised value description
1240 sub GetKohaAuthorisedValueLib
{
1241 my ($category,$authorised_value,$opac) = @_;
1243 my $dbh = C4
::Context
->dbh;
1244 my $sth = $dbh->prepare("select lib, lib_opac from authorised_values where category=? and authorised_value=?");
1245 $sth->execute($category,$authorised_value);
1246 my $data = $sth->fetchrow_hashref;
1247 $value = ($opac && $$data{'lib_opac'}) ?
$$data{'lib_opac'} : $$data{'lib'};
1251 =head2 display_marc_indicators
1253 my $display_form = C4::Koha::display_marc_indicators($field);
1255 C<$field> is a MARC::Field object
1257 Generate a display form of the indicators of a variable
1258 MARC field, replacing any blanks with '#'.
1262 sub display_marc_indicators
{
1264 my $indicators = '';
1265 if ($field && $field->tag() >= 10) {
1266 $indicators = $field->indicator(1) . $field->indicator(2);
1267 $indicators =~ s/ /#/g;
1272 sub GetNormalizedUPC
{
1273 my ($marcrecord,$marcflavour) = @_;
1275 return unless $marcrecord;
1276 if ($marcflavour eq 'UNIMARC') {
1277 my @fields = $marcrecord->field('072');
1278 foreach my $field (@fields) {
1279 my $upc = _normalize_match_point
($field->subfield('a'));
1286 else { # assume marc21 if not unimarc
1287 my @fields = $marcrecord->field('024');
1288 foreach my $field (@fields) {
1289 my $indicator = $field->indicator(1);
1290 my $upc = _normalize_match_point
($field->subfield('a'));
1291 if ($upc && $indicator == 1 ) {
1298 # Normalizes and returns the first valid ISBN found in the record
1299 # ISBN13 are converted into ISBN10. This is required to get some book cover images.
1300 sub GetNormalizedISBN
{
1301 my ($isbn,$marcrecord,$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) = split(/\|/, $isbn );
1306 return _isbn_cleanup
($isbn);
1309 return unless $marcrecord;
1311 if ($marcflavour eq 'UNIMARC') {
1312 my @fields = $marcrecord->field('010');
1313 foreach my $field (@fields) {
1314 my $isbn = $field->subfield('a');
1316 return _isbn_cleanup
($isbn);
1320 else { # assume marc21 if not unimarc
1321 my @fields = $marcrecord->field('020');
1322 foreach my $field (@fields) {
1323 $isbn = $field->subfield('a');
1325 return _isbn_cleanup
($isbn);
1331 sub GetNormalizedEAN
{
1332 my ($marcrecord,$marcflavour) = @_;
1334 return unless $marcrecord;
1336 if ($marcflavour eq 'UNIMARC') {
1337 my @fields = $marcrecord->field('073');
1338 foreach my $field (@fields) {
1339 my $ean = _normalize_match_point
($field->subfield('a'));
1345 else { # assume marc21 if not unimarc
1346 my @fields = $marcrecord->field('024');
1347 foreach my $field (@fields) {
1348 my $indicator = $field->indicator(1);
1349 my $ean = _normalize_match_point
($field->subfield('a'));
1350 if ( $ean && $indicator == 3 ) {
1357 sub GetNormalizedOCLCNumber
{
1358 my ($marcrecord,$marcflavour) = @_;
1359 return unless $marcrecord;
1361 if ($marcflavour ne 'UNIMARC' ) {
1362 my @fields = $marcrecord->field('035');
1363 foreach my $field (@fields) {
1364 my $oclc = $field->subfield('a');
1365 if ($oclc =~ /OCoLC/) {
1366 $oclc =~ s/\(OCoLC\)//;
1376 sub GetAuthvalueDropbox
{
1377 my ( $authcat, $default ) = @_;
1378 my $branch_limit = C4
::Context
->userenv ? C4
::Context
->userenv->{"branch"} : "";
1379 my $dbh = C4
::Context
->dbh;
1383 FROM authorised_values
1386 LEFT JOIN authorised_values_branches ON
( id
= av_id
)
1391 $query .= " AND ( branchcode = ? OR branchcode IS NULL )" if $branch_limit;
1392 $query .= " GROUP BY lib ORDER BY category, lib, lib_opac";
1393 my $sth = $dbh->prepare($query);
1394 $sth->execute( $authcat, $branch_limit ?
$branch_limit : () );
1397 my $option_list = [];
1398 my @authorised_values = ( q{} );
1399 while (my $av = $sth->fetchrow_hashref) {
1400 push @
{$option_list}, {
1401 value
=> $av->{authorised_value
},
1402 label
=> $av->{lib
},
1403 default => ($default eq $av->{authorised_value
}),
1407 if ( @
{$option_list} ) {
1408 return $option_list;
1414 =head2 GetDailyQuote($opts)
1416 Takes a hashref of options
1418 Currently supported options are:
1420 'id' An exact quote id
1421 'random' Select a random quote
1422 noop When no option is passed in, this sub will return the quote timestamped for the current day
1424 The function returns an anonymous hash following this format:
1427 'source' => 'source-of-quote',
1428 'timestamp' => 'timestamp-value',
1429 'text' => 'text-of-quote',
1435 # This is definitely a candidate for some sort of caching once we finally settle caching/persistence issues...
1436 # at least for default option
1440 my $dbh = C4
::Context
->dbh;
1445 $query = 'SELECT * FROM quotes WHERE id = ?';
1446 $sth = $dbh->prepare($query);
1447 $sth->execute($opts{'id'});
1448 $quote = $sth->fetchrow_hashref();
1450 elsif ($opts{'random'}) {
1451 # Fall through... we also return a random quote as a catch-all if all else fails
1454 $query = 'SELECT * FROM quotes WHERE timestamp LIKE CONCAT(CURRENT_DATE,\'%\') ORDER BY timestamp DESC LIMIT 0,1';
1455 $sth = $dbh->prepare($query);
1457 $quote = $sth->fetchrow_hashref();
1459 unless ($quote) { # if there are not matches, choose a random quote
1460 # get a list of all available quote ids
1461 $sth = C4
::Context
->dbh->prepare('SELECT count(*) FROM quotes;');
1463 my $range = ($sth->fetchrow_array)[0];
1464 # chose a random id within that range if there is more than one quote
1465 my $offset = int(rand($range));
1467 $query = 'SELECT * FROM quotes ORDER BY id LIMIT 1 OFFSET ?';
1468 $sth = C4
::Context
->dbh->prepare($query);
1469 # see http://www.perlmonks.org/?node_id=837422 for why
1470 # we're being verbose and using bind_param
1471 $sth->bind_param(1, $offset, SQL_INTEGER
);
1473 $quote = $sth->fetchrow_hashref();
1474 # update the timestamp for that quote
1475 $query = 'UPDATE quotes SET timestamp = ? WHERE id = ?';
1476 $sth = C4
::Context
->dbh->prepare($query);
1478 DateTime
::Format
::MySQL
->format_datetime( dt_from_string
() ),
1485 sub _normalize_match_point
{
1486 my $match_point = shift;
1487 (my $normalized_match_point) = $match_point =~ /([\d-]*[X]*)/;
1488 $normalized_match_point =~ s/-//g;
1490 return $normalized_match_point;
1495 return NormalizeISBN
(
1498 format
=> 'ISBN-10',
1504 =head2 NormalizedISBN
1506 my $isbns = NormalizedISBN({
1508 strip_hyphens => [0,1],
1509 format => ['ISBN-10', 'ISBN-13']
1512 Returns an isbn validated by Business::ISBN.
1513 Optionally strips hyphens and/or forces the isbn
1514 to be of the specified format.
1516 If the string cannot be validated as an isbn,
1524 my $string = $params->{isbn
};
1525 my $strip_hyphens = $params->{strip_hyphens
};
1526 my $format = $params->{format
};
1528 return unless $string;
1530 my $isbn = Business
::ISBN
->new($string);
1532 if ( $isbn && $isbn->is_valid() ) {
1534 if ( $format eq 'ISBN-10' ) {
1535 $isbn = $isbn->as_isbn10();
1537 elsif ( $format eq 'ISBN-13' ) {
1538 $isbn = $isbn->as_isbn13();
1540 return unless $isbn;
1542 if ($strip_hyphens) {
1543 $string = $isbn->as_string( [] );
1545 $string = $isbn->as_string();
1552 =head2 GetVariationsOfISBN
1554 my @isbns = GetVariationsOfISBN( $isbn );
1556 Returns a list of variations of the given isbn in
1557 both ISBN-10 and ISBN-13 formats, with and without
1560 In a scalar context, the isbns are returned as a
1561 string delimited by ' | '.
1565 sub GetVariationsOfISBN
{
1568 return unless $isbn;
1572 push( @isbns, NormalizeISBN
({ isbn
=> $isbn }) );
1573 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-10' }) );
1574 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-13' }) );
1575 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-10', strip_hyphens
=> 1 }) );
1576 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-13', strip_hyphens
=> 1 }) );
1578 # Strip out any "empty" strings from the array
1579 @isbns = grep { defined($_) && $_ =~ /\S/ } @isbns;
1581 return wantarray ?
@isbns : join( " | ", @isbns );
1584 =head2 GetVariationsOfISBNs
1586 my @isbns = GetVariationsOfISBNs( @isbns );
1588 Returns a list of variations of the given isbns in
1589 both ISBN-10 and ISBN-13 formats, with and without
1592 In a scalar context, the isbns are returned as a
1593 string delimited by ' | '.
1597 sub GetVariationsOfISBNs
{
1600 @isbns = map { GetVariationsOfISBN
( $_ ) } @isbns;
1602 return wantarray ?
@isbns : join( " | ", @isbns );
1605 =head2 IsKohaFieldLinked
1607 my $is_linked = IsKohaFieldLinked({
1608 kohafield => $kohafield,
1609 frameworkcode => $frameworkcode,
1612 Return 1 if the field is linked
1616 sub IsKohaFieldLinked
{
1617 my ( $params ) = @_;
1618 my $kohafield = $params->{kohafield
};
1619 my $frameworkcode = $params->{frameworkcode
} || '';
1620 my $dbh = C4
::Context
->dbh;
1621 my $is_linked = $dbh->selectcol_arrayref( q
|
1623 FROM marc_subfield_structure
1624 WHERE frameworkcode
= ?
1626 |,{}, $frameworkcode, $kohafield );
1627 return $is_linked->[0];