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 &getframeworks &getframeworkinfo
49 &get_notforloan_label_of
52 &getitemtypeimagelocation
54 &GetAuthorisedValueCategories
55 &GetKohaAuthorisedValues
56 &GetKohaAuthorisedValuesFromField
57 &GetKohaAuthorisedValuesMapping
58 &GetAuthorisedValueByCode
63 &GetNormalizedOCLCNumber
73 @EXPORT_OK = qw( GetDailyQuote );
78 C4::Koha - Perl Module containing convenience functions for Koha scripts
86 Koha.pm provides many functions for Koha scripts.
94 $itemtypes = &GetItemTypes( style => $style );
96 Returns information about existing itemtypes.
99 style: either 'array' or 'hash', defaults to 'hash'.
100 'array' returns an arrayref,
101 'hash' return a hashref with the itemtype value as the key
103 build a HTML select with the following code :
105 =head3 in PERL SCRIPT
107 my $itemtypes = GetItemTypes;
109 foreach my $thisitemtype (sort keys %$itemtypes) {
110 my $selected = 1 if $thisitemtype eq $itemtype;
111 my %row =(value => $thisitemtype,
112 selected => $selected,
113 description => $itemtypes->{$thisitemtype}->{'description'},
115 push @itemtypesloop, \%row;
117 $template->param(itemtypeloop => \@itemtypesloop);
121 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
122 <select name="itemtype">
123 <option value="">Default</option>
124 <!-- TMPL_LOOP name="itemtypeloop" -->
125 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="description" --></option>
128 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
129 <input type="submit" value="OK" class="button">
136 my $style = defined( $params{'style'} ) ?
$params{'style'} : 'hash';
138 require C4
::Languages
;
139 my $language = C4
::Languages
::getlanguage
();
140 # returns a reference to a hash of references to itemtypes...
141 my $dbh = C4
::Context
->dbh;
145 itemtypes
.description
,
146 itemtypes
.rentalcharge
,
147 itemtypes
.notforloan
,
150 itemtypes
.checkinmsg
,
151 itemtypes
.checkinmsgtype
,
152 itemtypes
.sip_media_type
,
153 itemtypes
.hideinopac
,
154 itemtypes
.searchcategory
,
155 COALESCE
( localization
.translation
, itemtypes
.description
) AS translated_description
157 LEFT JOIN localization ON itemtypes
.itemtype
= localization
.code
158 AND localization
.entity
= 'itemtypes'
159 AND localization
.lang
= ?
162 my $sth = $dbh->prepare($query);
163 $sth->execute( $language );
165 if ( $style eq 'hash' ) {
167 while ( my $IT = $sth->fetchrow_hashref ) {
168 $itemtypes{ $IT->{'itemtype'} } = $IT;
170 return ( \
%itemtypes );
172 return [ sort { lc $a->{translated_description
} cmp lc $b->{translated_description
} } @
{ $sth->fetchall_arrayref( {} ) } ];
176 =head2 GetItemTypesCategorized
178 $categories = GetItemTypesCategorized();
180 Returns a hashref containing search categories.
181 A search category will be put in the hash if at least one of its itemtypes is visible in OPAC.
182 The categories must be part of Authorized Values (ITEMTYPECAT)
186 sub GetItemTypesCategorized
{
187 my $dbh = C4
::Context
->dbh;
188 # Order is important, so that partially hidden (some items are not visible in OPAC) search
189 # categories will be visible. hideinopac=0 must be last.
191 SELECT itemtype
, description
, imageurl
, hideinopac
, 0 as
'iscat' FROM itemtypes WHERE ISNULL
(searchcategory
) or length(searchcategory
) = 0
193 SELECT DISTINCT searchcategory AS
`itemtype`,
194 authorised_values
.lib_opac AS description
,
195 authorised_values
.imageurl AS imageurl
,
196 hideinopac
, 1 as
'iscat'
198 LEFT JOIN authorised_values ON searchcategory
= authorised_value
199 WHERE searchcategory
> '' and hideinopac
=1
201 SELECT DISTINCT searchcategory AS
`itemtype`,
202 authorised_values
.lib_opac AS description
,
203 authorised_values
.imageurl AS imageurl
,
204 hideinopac
, 1 as
'iscat'
206 LEFT JOIN authorised_values ON searchcategory
= authorised_value
207 WHERE searchcategory
> '' and hideinopac
=0
209 return ($dbh->selectall_hashref($query,'itemtype'));
212 =head2 GetItemTypesByCategory
214 @results = GetItemTypesByCategory( $searchcategory );
216 Returns the itemtype code of all itemtypes included in a searchcategory.
220 sub GetItemTypesByCategory
{
224 my $dbh = C4
::Context
->dbh;
225 my $query = qq|SELECT itemtype FROM itemtypes WHERE searchcategory
=?
|;
226 my $tmp=$dbh->selectcol_arrayref($query,undef,$category);
232 $frameworks = &getframework();
234 Returns information about existing frameworks
236 build a HTML select with the following code :
238 =head3 in PERL SCRIPT
240 my $frameworks = getframeworks();
242 foreach my $thisframework (keys %$frameworks) {
243 my $selected = 1 if $thisframework eq $frameworkcode;
245 value => $thisframework,
246 selected => $selected,
247 description => $frameworks->{$thisframework}->{'frameworktext'},
249 push @frameworksloop, \%row;
251 $template->param(frameworkloop => \@frameworksloop);
255 <form action="[% script_name %] method=post>
256 <select name="frameworkcode">
257 <option value="">Default</option>
258 [% FOREACH framework IN frameworkloop %]
259 [% IF ( framework.selected ) %]
260 <option value="[% framework.value %]" selected="selected">[% framework.description %]</option>
262 <option value="[% framework.value %]">[% framework.description %]</option>
266 <input type=text name=searchfield value="[% searchfield %]">
267 <input type="submit" value="OK" class="button">
274 # returns a reference to a hash of references to branches...
276 my $dbh = C4
::Context
->dbh;
277 my $sth = $dbh->prepare("select * from biblio_framework");
279 while ( my $IT = $sth->fetchrow_hashref ) {
280 $itemtypes{ $IT->{'frameworkcode'} } = $IT;
282 return ( \
%itemtypes );
285 =head2 GetFrameworksLoop
287 $frameworks = GetFrameworksLoop( $frameworkcode );
289 Returns the loop suggested on getframework(), but ordered by framework description.
291 build a HTML select with the following code :
293 =head3 in PERL SCRIPT
295 $template->param( frameworkloop => GetFrameworksLoop( $frameworkcode ) );
299 Same as getframework()
301 <form action="[% script_name %] method=post>
302 <select name="frameworkcode">
303 <option value="">Default</option>
304 [% FOREACH framework IN frameworkloop %]
305 [% IF ( framework.selected ) %]
306 <option value="[% framework.value %]" selected="selected">[% framework.description %]</option>
308 <option value="[% framework.value %]">[% framework.description %]</option>
312 <input type=text name=searchfield value="[% searchfield %]">
313 <input type="submit" value="OK" class="button">
318 sub GetFrameworksLoop
{
319 my $frameworkcode = shift;
320 my $frameworks = getframeworks
();
322 foreach my $thisframework (sort { uc($frameworks->{$a}->{'frameworktext'}) cmp uc($frameworks->{$b}->{'frameworktext'}) } keys %$frameworks) {
323 my $selected = ( $thisframework eq $frameworkcode ) ?
1 : undef;
325 value
=> $thisframework,
326 selected
=> $selected,
327 description
=> $frameworks->{$thisframework}->{'frameworktext'},
329 push @frameworkloop, \
%row;
331 return \
@frameworkloop;
334 =head2 getframeworkinfo
336 $frameworkinfo = &getframeworkinfo($frameworkcode);
338 Returns information about an frameworkcode.
342 sub getframeworkinfo
{
343 my ($frameworkcode) = @_;
344 my $dbh = C4
::Context
->dbh;
346 $dbh->prepare("select * from biblio_framework where frameworkcode=?");
347 $sth->execute($frameworkcode);
348 my $res = $sth->fetchrow_hashref;
352 =head2 getitemtypeinfo
354 $itemtype = &getitemtypeinfo($itemtype, [$interface]);
356 Returns information about an itemtype. The optional $interface argument
357 sets which interface ('opac' or 'intranet') to return the imageurl for.
358 Defaults to intranet.
362 sub getitemtypeinfo
{
363 my ($itemtype, $interface) = @_;
364 my $dbh = C4
::Context
->dbh;
365 require C4
::Languages
;
366 my $language = C4
::Languages
::getlanguage
();
367 my $it = $dbh->selectrow_hashref(q
|
370 itemtypes
.description
,
371 itemtypes
.rentalcharge
,
372 itemtypes
.notforloan
,
375 itemtypes
.checkinmsg
,
376 itemtypes
.checkinmsgtype
,
377 itemtypes
.sip_media_type
,
378 COALESCE
( localization
.translation
, itemtypes
.description
) AS translated_description
380 LEFT JOIN localization ON itemtypes
.itemtype
= localization
.code
381 AND localization
.entity
= 'itemtypes'
382 AND localization
.lang
= ?
383 WHERE itemtypes
.itemtype
= ?
384 |, undef, $language, $itemtype );
386 $it->{imageurl
} = getitemtypeimagelocation
( ( ( defined $interface && $interface eq 'opac' ) ?
'opac' : 'intranet' ), $it->{imageurl
} );
391 =head2 getitemtypeimagedir
393 my $directory = getitemtypeimagedir( 'opac' );
395 pass in 'opac' or 'intranet'. Defaults to 'opac'.
397 returns the full path to the appropriate directory containing images.
401 sub getitemtypeimagedir
{
402 my $src = shift || 'opac';
403 if ($src eq 'intranet') {
404 return C4
::Context
->config('intrahtdocs') . '/' .C4
::Context
->preference('template') . '/img/itemtypeimg';
406 return C4
::Context
->config('opachtdocs') . '/' . C4
::Context
->preference('opacthemes') . '/itemtypeimg';
410 sub getitemtypeimagesrc
{
411 my $src = shift || 'opac';
412 if ($src eq 'intranet') {
413 return '/intranet-tmpl' . '/' . C4
::Context
->preference('template') . '/img/itemtypeimg';
415 return '/opac-tmpl' . '/' . C4
::Context
->preference('opacthemes') . '/itemtypeimg';
419 sub getitemtypeimagelocation
{
420 my ( $src, $image ) = @_;
422 return '' if ( !$image );
425 my $scheme = ( URI
::Split
::uri_split
( $image ) )[0];
427 return $image if ( $scheme );
429 return getitemtypeimagesrc
( $src ) . '/' . $image;
432 =head3 _getImagesFromDirectory
434 Find all of the image files in a directory in the filesystem
436 parameters: a directory name
438 returns: a list of images in that directory.
440 Notes: this does not traverse into subdirectories. See
441 _getSubdirectoryNames for help with that.
442 Images are assumed to be files with .gif or .png file extensions.
443 The image names returned do not have the directory name on them.
447 sub _getImagesFromDirectory
{
448 my $directoryname = shift;
449 return unless defined $directoryname;
450 return unless -d
$directoryname;
452 if ( opendir ( my $dh, $directoryname ) ) {
453 my @images = grep { /\.(gif|png)$/i } readdir( $dh );
455 @images = sort(@images);
458 warn "unable to opendir $directoryname: $!";
463 =head3 _getSubdirectoryNames
465 Find all of the directories in a directory in the filesystem
467 parameters: a directory name
469 returns: a list of subdirectories in that directory.
471 Notes: this does not traverse into subdirectories. Only the first
472 level of subdirectories are returned.
473 The directory names returned don't have the parent directory name on them.
477 sub _getSubdirectoryNames
{
478 my $directoryname = shift;
479 return unless defined $directoryname;
480 return unless -d
$directoryname;
482 if ( opendir ( my $dh, $directoryname ) ) {
483 my @directories = grep { -d File
::Spec
->catfile( $directoryname, $_ ) && ! ( /^\./ ) } readdir( $dh );
487 warn "unable to opendir $directoryname: $!";
494 returns: a listref of hashrefs. Each hash represents another collection of images.
496 { imagesetname => 'npl', # the name of the image set (npl is the original one)
497 images => listref of image hashrefs
500 each image is represented by a hashref like this:
502 { KohaImage => 'npl/image.gif',
503 StaffImageUrl => '/intranet-tmpl/prog/img/itemtypeimg/npl/image.gif',
504 OpacImageURL => '/opac-tmpl/prog/itemtypeimg/npl/image.gif'
505 checked => 0 or 1: was this the image passed to this method?
506 Note: I'd like to remove this somehow.
513 my $checked = $params{'checked'} || '';
515 my $paths = { staff
=> { filesystem
=> getitemtypeimagedir
('intranet'),
516 url
=> getitemtypeimagesrc
('intranet'),
518 opac
=> { filesystem
=> getitemtypeimagedir
('opac'),
519 url
=> getitemtypeimagesrc
('opac'),
523 my @imagesets = (); # list of hasrefs of image set data to pass to template
524 my @subdirectories = _getSubdirectoryNames
( $paths->{'staff'}{'filesystem'} );
525 foreach my $imagesubdir ( @subdirectories ) {
526 warn $imagesubdir if $DEBUG;
527 my @imagelist = (); # hashrefs of image info
528 my @imagenames = _getImagesFromDirectory
( File
::Spec
->catfile( $paths->{'staff'}{'filesystem'}, $imagesubdir ) );
529 my $imagesetactive = 0;
530 foreach my $thisimage ( @imagenames ) {
532 { KohaImage
=> "$imagesubdir/$thisimage",
533 StaffImageUrl
=> join( '/', $paths->{'staff'}{'url'}, $imagesubdir, $thisimage ),
534 OpacImageUrl
=> join( '/', $paths->{'opac'}{'url'}, $imagesubdir, $thisimage ),
535 checked
=> "$imagesubdir/$thisimage" eq $checked ?
1 : 0,
538 $imagesetactive = 1 if "$imagesubdir/$thisimage" eq $checked;
540 push @imagesets, { imagesetname
=> $imagesubdir,
541 imagesetactive
=> $imagesetactive,
542 images
=> \
@imagelist };
550 $printers = &GetPrinters();
551 @queues = keys %$printers;
553 Returns information about existing printer queues.
555 C<$printers> is a reference-to-hash whose keys are the print queues
556 defined in the printers table of the Koha database. The values are
557 references-to-hash, whose keys are the fields in the printers table.
563 my $dbh = C4
::Context
->dbh;
564 my $sth = $dbh->prepare("select * from printers");
566 while ( my $printer = $sth->fetchrow_hashref ) {
567 $printers{ $printer->{'printqueue'} } = $printer;
569 return ( \
%printers );
574 $printer = GetPrinter( $query, $printers );
579 my ( $query, $printers ) = @_; # get printer for this query from printers
580 my $printer = $query->param('printer');
581 my %cookie = $query->cookie('userenv');
582 ($printer) || ( $printer = $cookie{'printer'} ) || ( $printer = '' );
583 ( $printers->{$printer} ) || ( $printer = ( keys %$printers )[0] );
589 Returns the number of pages to display in a pagination bar, given the number
590 of items and the number of items per page.
595 my ( $nb_items, $nb_items_per_page ) = @_;
597 return int( ( $nb_items - 1 ) / $nb_items_per_page ) + 1;
602 (@themes) = &getallthemes('opac');
603 (@themes) = &getallthemes('intranet');
605 Returns an array of all available themes.
613 if ( $type eq 'intranet' ) {
614 $htdocs = C4
::Context
->config('intrahtdocs');
617 $htdocs = C4
::Context
->config('opachtdocs');
619 opendir D
, "$htdocs";
620 my @dirlist = readdir D
;
621 foreach my $directory (@dirlist) {
622 next if $directory eq 'lib';
623 -d
"$htdocs/$directory/en" and push @themes, $directory;
630 if ( C4
::Context
->preference("marcflavour") eq "UNIMARC" ) {
635 tags
=> [ qw
/ 600ab 601ab 602a 604at 605a 606ax 610a / ],
641 tags
=> [ qw
/ 607a / ],
647 tags
=> [ qw
/ 500a 501a 503a / ],
653 tags
=> [ qw
/ 700ab 701ab 702ab / ],
654 sep
=> C4
::Context
->preference("UNIMARCAuthorsFacetsSeparator"),
659 tags
=> [ qw
/ 225a / ],
665 tags
=> [ qw
/ 995e / ],
669 unless ( Koha
::Libraries
->search->count == 1 )
671 my $DisplayLibraryFacets = C4
::Context
->preference('DisplayLibraryFacets');
672 if ( $DisplayLibraryFacets eq 'both'
673 || $DisplayLibraryFacets eq 'holding' )
678 idx
=> 'holdingbranch',
679 label
=> 'HoldingLibrary',
680 tags
=> [qw
/ 995c /],
685 if ( $DisplayLibraryFacets eq 'both'
686 || $DisplayLibraryFacets eq 'home' )
692 label
=> 'HomeLibrary',
693 tags
=> [qw
/ 995b /],
704 tags
=> [ qw
/ 650a / ],
709 # label => 'People and Organizations',
710 # tags => [ qw/ 600a 610a 611a / ],
716 tags
=> [ qw
/ 651a / ],
722 tags
=> [ qw
/ 630a / ],
728 tags
=> [ qw
/ 100a 110a 700a / ],
734 tags
=> [ qw
/ 440a 490a / ],
739 label
=> 'ItemTypes',
740 tags
=> [ qw
/ 952y 942c / ],
746 tags
=> [ qw
/ 952c / ],
750 unless ( Koha
::Libraries
->search->count == 1 )
752 my $DisplayLibraryFacets = C4
::Context
->preference('DisplayLibraryFacets');
753 if ( $DisplayLibraryFacets eq 'both'
754 || $DisplayLibraryFacets eq 'holding' )
759 idx
=> 'holdingbranch',
760 label
=> 'HoldingLibrary',
761 tags
=> [qw
/ 952b /],
766 if ( $DisplayLibraryFacets eq 'both'
767 || $DisplayLibraryFacets eq 'home' )
773 label
=> 'HomeLibrary',
774 tags
=> [qw
/ 952a /],
785 Return a href where a key is associated to a href. You give a query,
786 the name of the key among the fields returned by the query. If you
787 also give as third argument the name of the value, the function
788 returns a href of scalar. The optional 4th argument is an arrayref of
789 items passed to the C<execute()> call. It is designed to bind
790 parameters to any placeholders in your SQL.
799 # generic href of any information on the item, href of href.
800 my $iteminfos_of = get_infos_of($query, 'itemnumber');
801 print $iteminfos_of->{$itemnumber}{barcode};
803 # specific information, href of scalar
804 my $barcode_of_item = get_infos_of($query, 'itemnumber', 'barcode');
805 print $barcode_of_item->{$itemnumber};
810 my ( $query, $key_name, $value_name, $bind_params ) = @_;
812 my $dbh = C4
::Context
->dbh;
814 my $sth = $dbh->prepare($query);
815 $sth->execute( @
$bind_params );
818 while ( my $row = $sth->fetchrow_hashref ) {
819 if ( defined $value_name ) {
820 $infos_of{ $row->{$key_name} } = $row->{$value_name};
823 $infos_of{ $row->{$key_name} } = $row;
831 =head2 get_notforloan_label_of
833 my $notforloan_label_of = get_notforloan_label_of();
835 Each authorised value of notforloan (information available in items and
836 itemtypes) is link to a single label.
838 Returns a href where keys are authorised values and values are corresponding
841 foreach my $authorised_value (keys %{$notforloan_label_of}) {
843 "authorised_value: %s => %s\n",
845 $notforloan_label_of->{$authorised_value}
851 # FIXME - why not use GetAuthorisedValues ??
853 sub get_notforloan_label_of
{
854 my $dbh = C4
::Context
->dbh;
857 SELECT authorised_value
858 FROM marc_subfield_structure
859 WHERE kohafield = \'items.notforloan\'
862 my $sth = $dbh->prepare($query);
864 my ($statuscode) = $sth->fetchrow_array();
869 FROM authorised_values
872 $sth = $dbh->prepare($query);
873 $sth->execute($statuscode);
874 my %notforloan_label_of;
875 while ( my $row = $sth->fetchrow_hashref ) {
876 $notforloan_label_of{ $row->{authorised_value
} } = $row->{lib
};
880 return \
%notforloan_label_of;
883 =head2 GetAuthValCode
885 $authvalcode = GetAuthValCode($kohafield,$frameworkcode);
890 my ($kohafield,$fwcode) = @_;
891 my $dbh = C4
::Context
->dbh;
892 $fwcode='' unless $fwcode;
893 my $sth = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield=? and frameworkcode=?');
894 $sth->execute($kohafield,$fwcode);
895 my ($authvalcode) = $sth->fetchrow_array;
899 =head2 GetAuthValCodeFromField
901 $authvalcode = GetAuthValCodeFromField($field,$subfield,$frameworkcode);
903 C<$subfield> can be undefined
907 sub GetAuthValCodeFromField
{
908 my ($field,$subfield,$fwcode) = @_;
909 my $dbh = C4
::Context
->dbh;
910 $fwcode='' unless $fwcode;
912 if (defined $subfield) {
913 $sth = $dbh->prepare('select authorised_value from marc_subfield_structure where tagfield=? and tagsubfield=? and frameworkcode=?');
914 $sth->execute($field,$subfield,$fwcode);
916 $sth = $dbh->prepare('select authorised_value from marc_tag_structure where tagfield=? and frameworkcode=?');
917 $sth->execute($field,$fwcode);
919 my ($authvalcode) = $sth->fetchrow_array;
923 =head2 GetAuthorisedValues
925 $authvalues = GetAuthorisedValues([$category]);
927 This function returns all authorised values from the'authorised_value' table in a reference to array of hashrefs.
929 C<$category> returns authorised values for just one category (optional).
931 C<$opac> If set to a true value, displays OPAC descriptions rather than normal ones when they exist.
935 sub GetAuthorisedValues
{
936 my ( $category, $opac ) = @_;
938 # Is this cached already?
939 $opac = $opac ?
1 : 0; # normalise to be safe
941 C4
::Context
->userenv ? C4
::Context
->userenv->{"branch"} : "";
943 "AuthorisedValues-$category-$opac-$branch_limit";
944 my $cache = Koha
::Caches
->get_instance();
945 my $result = $cache->get_from_cache($cache_key);
946 return $result if $result;
949 my $dbh = C4
::Context
->dbh;
952 FROM authorised_values av
955 LEFT JOIN authorised_values_branches ON
( id
= av_id
)
960 push @where_strings, "category = ?";
961 push @where_args, $category;
964 push @where_strings, "( branchcode = ? OR branchcode IS NULL )";
965 push @where_args, $branch_limit;
967 if(@where_strings > 0) {
968 $query .= " WHERE " . join(" AND ", @where_strings);
970 $query .= ' ORDER BY category, ' . (
971 $opac ?
'COALESCE(lib_opac, lib)'
975 my $sth = $dbh->prepare($query);
977 $sth->execute( @where_args );
978 while (my $data=$sth->fetchrow_hashref) {
979 if ($opac && $data->{lib_opac
}) {
980 $data->{lib
} = $data->{lib_opac
};
982 push @results, $data;
986 $cache->set_in_cache( $cache_key, \
@results, { expiry
=> 5 } );
990 =head2 GetAuthorisedValueCategories
992 $auth_categories = GetAuthorisedValueCategories();
994 Return an arrayref of all of the available authorised
999 sub GetAuthorisedValueCategories
{
1000 my $dbh = C4
::Context
->dbh;
1001 my $sth = $dbh->prepare("SELECT DISTINCT category FROM authorised_values ORDER BY category");
1004 while (defined (my $category = $sth->fetchrow_array) ) {
1005 push @results, $category;
1010 =head2 GetAuthorisedValueByCode
1012 $authorised_value = GetAuthorisedValueByCode( $category, $authvalcode, $opac );
1014 Return the lib attribute from authorised_values from the row identified
1015 by the passed category and code
1019 sub GetAuthorisedValueByCode
{
1020 my ( $category, $authvalcode, $opac ) = @_;
1022 my $field = $opac ?
'lib_opac' : 'lib';
1023 my $dbh = C4
::Context
->dbh;
1024 my $sth = $dbh->prepare("SELECT $field FROM authorised_values WHERE category=? AND authorised_value =?");
1025 $sth->execute( $category, $authvalcode );
1026 while ( my $data = $sth->fetchrow_hashref ) {
1027 return $data->{ $field };
1031 =head2 GetKohaAuthorisedValues
1033 Takes $kohafield, $fwcode as parameters.
1035 If $opac parameter is set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1037 Returns hashref of Code => description
1039 Returns undef if no authorised value category is defined for the kohafield.
1043 sub GetKohaAuthorisedValues
{
1044 my ($kohafield,$fwcode,$opac) = @_;
1045 $fwcode='' unless $fwcode;
1047 my $dbh = C4
::Context
->dbh;
1048 my $avcode = GetAuthValCode
($kohafield,$fwcode);
1050 my $sth = $dbh->prepare("select authorised_value, lib, lib_opac from authorised_values where category=? ");
1051 $sth->execute($avcode);
1052 while ( my ($val, $lib, $lib_opac) = $sth->fetchrow_array ) {
1053 $values{$val} = ($opac && $lib_opac) ?
$lib_opac : $lib;
1061 =head2 GetKohaAuthorisedValuesFromField
1063 Takes $field, $subfield, $fwcode as parameters.
1065 If $opac parameter is set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1066 $subfield can be undefined
1068 Returns hashref of Code => description
1070 Returns undef if no authorised value category is defined for the given field and subfield
1074 sub GetKohaAuthorisedValuesFromField
{
1075 my ($field, $subfield, $fwcode,$opac) = @_;
1076 $fwcode='' unless $fwcode;
1078 my $dbh = C4
::Context
->dbh;
1079 my $avcode = GetAuthValCodeFromField
($field, $subfield, $fwcode);
1081 my $sth = $dbh->prepare("select authorised_value, lib, lib_opac from authorised_values where category=? ");
1082 $sth->execute($avcode);
1083 while ( my ($val, $lib, $lib_opac) = $sth->fetchrow_array ) {
1084 $values{$val} = ($opac && $lib_opac) ?
$lib_opac : $lib;
1092 =head2 GetKohaAuthorisedValuesMapping
1094 Takes a hash as a parameter. The interface key indicates the
1095 description to use in the mapping.
1098 "{kohafield},{frameworkcode},{authorised_value}" => "{description}"
1099 for all the kohafields, frameworkcodes, and authorised values.
1101 Returns undef if nothing is found.
1105 sub GetKohaAuthorisedValuesMapping
{
1106 my ($parameter) = @_;
1107 my $interface = $parameter->{'interface'} // '';
1109 my $query_mapping = q{
1110 SELECT TA.kohafield,TA.authorised_value AS category,
1111 TA.frameworkcode,TB.authorised_value,
1112 IF(TB.lib_opac>'',TB.lib_opac,TB.lib) AS OPAC,
1113 TB.lib AS Intranet,TB.lib_opac
1114 FROM marc_subfield_structure AS TA JOIN
1115 authorised_values as TB ON
1116 TA.authorised_value=TB.category
1117 WHERE TA.kohafield>'' AND TA.authorised_value>'';
1119 my $dbh = C4
::Context
->dbh;
1120 my $sth = $dbh->prepare($query_mapping);
1123 if ($interface eq 'opac') {
1124 while (my $row = $sth->fetchrow_hashref) {
1125 $avmapping->{$row->{kohafield
}.",".$row->{frameworkcode
}.",".$row->{authorised_value
}} = $row->{OPAC
};
1129 while (my $row = $sth->fetchrow_hashref) {
1130 $avmapping->{$row->{kohafield
}.",".$row->{frameworkcode
}.",".$row->{authorised_value
}} = $row->{Intranet
};
1138 my $escaped_string = C4::Koha::xml_escape($string);
1140 Convert &, <, >, ', and " in a string to XML entities
1146 return '' unless defined $str;
1147 $str =~ s/&/&/g;
1150 $str =~ s/'/'/g;
1151 $str =~ s/"/"/g;
1155 =head2 display_marc_indicators
1157 my $display_form = C4::Koha::display_marc_indicators($field);
1159 C<$field> is a MARC::Field object
1161 Generate a display form of the indicators of a variable
1162 MARC field, replacing any blanks with '#'.
1166 sub display_marc_indicators
{
1168 my $indicators = '';
1169 if ($field && $field->tag() >= 10) {
1170 $indicators = $field->indicator(1) . $field->indicator(2);
1171 $indicators =~ s/ /#/g;
1176 sub GetNormalizedUPC
{
1177 my ($marcrecord,$marcflavour) = @_;
1179 return unless $marcrecord;
1180 if ($marcflavour eq 'UNIMARC') {
1181 my @fields = $marcrecord->field('072');
1182 foreach my $field (@fields) {
1183 my $upc = _normalize_match_point
($field->subfield('a'));
1190 else { # assume marc21 if not unimarc
1191 my @fields = $marcrecord->field('024');
1192 foreach my $field (@fields) {
1193 my $indicator = $field->indicator(1);
1194 my $upc = _normalize_match_point
($field->subfield('a'));
1195 if ($upc && $indicator == 1 ) {
1202 # Normalizes and returns the first valid ISBN found in the record
1203 # ISBN13 are converted into ISBN10. This is required to get some book cover images.
1204 sub GetNormalizedISBN
{
1205 my ($isbn,$marcrecord,$marcflavour) = @_;
1207 # Koha attempts to store multiple ISBNs in biblioitems.isbn, separated by " | "
1208 # anything after " | " should be removed, along with the delimiter
1209 ($isbn) = split(/\|/, $isbn );
1210 return _isbn_cleanup
($isbn);
1213 return unless $marcrecord;
1215 if ($marcflavour eq 'UNIMARC') {
1216 my @fields = $marcrecord->field('010');
1217 foreach my $field (@fields) {
1218 my $isbn = $field->subfield('a');
1220 return _isbn_cleanup
($isbn);
1224 else { # assume marc21 if not unimarc
1225 my @fields = $marcrecord->field('020');
1226 foreach my $field (@fields) {
1227 $isbn = $field->subfield('a');
1229 return _isbn_cleanup
($isbn);
1235 sub GetNormalizedEAN
{
1236 my ($marcrecord,$marcflavour) = @_;
1238 return unless $marcrecord;
1240 if ($marcflavour eq 'UNIMARC') {
1241 my @fields = $marcrecord->field('073');
1242 foreach my $field (@fields) {
1243 my $ean = _normalize_match_point
($field->subfield('a'));
1249 else { # assume marc21 if not unimarc
1250 my @fields = $marcrecord->field('024');
1251 foreach my $field (@fields) {
1252 my $indicator = $field->indicator(1);
1253 my $ean = _normalize_match_point
($field->subfield('a'));
1254 if ( $ean && $indicator == 3 ) {
1261 sub GetNormalizedOCLCNumber
{
1262 my ($marcrecord,$marcflavour) = @_;
1263 return unless $marcrecord;
1265 if ($marcflavour ne 'UNIMARC' ) {
1266 my @fields = $marcrecord->field('035');
1267 foreach my $field (@fields) {
1268 my $oclc = $field->subfield('a');
1269 if ($oclc =~ /OCoLC/) {
1270 $oclc =~ s/\(OCoLC\)//;
1280 sub GetAuthvalueDropbox
{
1281 my ( $authcat, $default ) = @_;
1282 my $branch_limit = C4
::Context
->userenv ? C4
::Context
->userenv->{"branch"} : "";
1283 my $dbh = C4
::Context
->dbh;
1287 FROM authorised_values
1290 LEFT JOIN authorised_values_branches ON
( id
= av_id
)
1295 $query .= " AND ( branchcode = ? OR branchcode IS NULL )" if $branch_limit;
1296 $query .= " GROUP BY lib ORDER BY category, lib, lib_opac";
1297 my $sth = $dbh->prepare($query);
1298 $sth->execute( $authcat, $branch_limit ?
$branch_limit : () );
1301 my $option_list = [];
1302 my @authorised_values = ( q{} );
1303 while (my $av = $sth->fetchrow_hashref) {
1304 push @
{$option_list}, {
1305 value
=> $av->{authorised_value
},
1306 label
=> $av->{lib
},
1307 default => ($default eq $av->{authorised_value
}),
1311 if ( @
{$option_list} ) {
1312 return $option_list;
1318 =head2 GetDailyQuote($opts)
1320 Takes a hashref of options
1322 Currently supported options are:
1324 'id' An exact quote id
1325 'random' Select a random quote
1326 noop When no option is passed in, this sub will return the quote timestamped for the current day
1328 The function returns an anonymous hash following this format:
1331 'source' => 'source-of-quote',
1332 'timestamp' => 'timestamp-value',
1333 'text' => 'text-of-quote',
1339 # This is definitely a candidate for some sort of caching once we finally settle caching/persistence issues...
1340 # at least for default option
1344 my $dbh = C4
::Context
->dbh;
1349 $query = 'SELECT * FROM quotes WHERE id = ?';
1350 $sth = $dbh->prepare($query);
1351 $sth->execute($opts{'id'});
1352 $quote = $sth->fetchrow_hashref();
1354 elsif ($opts{'random'}) {
1355 # Fall through... we also return a random quote as a catch-all if all else fails
1358 $query = 'SELECT * FROM quotes WHERE timestamp LIKE CONCAT(CURRENT_DATE,\'%\') ORDER BY timestamp DESC LIMIT 0,1';
1359 $sth = $dbh->prepare($query);
1361 $quote = $sth->fetchrow_hashref();
1363 unless ($quote) { # if there are not matches, choose a random quote
1364 # get a list of all available quote ids
1365 $sth = C4
::Context
->dbh->prepare('SELECT count(*) FROM quotes;');
1367 my $range = ($sth->fetchrow_array)[0];
1368 # chose a random id within that range if there is more than one quote
1369 my $offset = int(rand($range));
1371 $query = 'SELECT * FROM quotes ORDER BY id LIMIT 1 OFFSET ?';
1372 $sth = C4
::Context
->dbh->prepare($query);
1373 # see http://www.perlmonks.org/?node_id=837422 for why
1374 # we're being verbose and using bind_param
1375 $sth->bind_param(1, $offset, SQL_INTEGER
);
1377 $quote = $sth->fetchrow_hashref();
1378 # update the timestamp for that quote
1379 $query = 'UPDATE quotes SET timestamp = ? WHERE id = ?';
1380 $sth = C4
::Context
->dbh->prepare($query);
1382 DateTime
::Format
::MySQL
->format_datetime( dt_from_string
() ),
1389 sub _normalize_match_point
{
1390 my $match_point = shift;
1391 (my $normalized_match_point) = $match_point =~ /([\d-]*[X]*)/;
1392 $normalized_match_point =~ s/-//g;
1394 return $normalized_match_point;
1399 return NormalizeISBN
(
1402 format
=> 'ISBN-10',
1408 =head2 NormalizedISBN
1410 my $isbns = NormalizedISBN({
1412 strip_hyphens => [0,1],
1413 format => ['ISBN-10', 'ISBN-13']
1416 Returns an isbn validated by Business::ISBN.
1417 Optionally strips hyphens and/or forces the isbn
1418 to be of the specified format.
1420 If the string cannot be validated as an isbn,
1428 my $string = $params->{isbn
};
1429 my $strip_hyphens = $params->{strip_hyphens
};
1430 my $format = $params->{format
};
1432 return unless $string;
1434 my $isbn = Business
::ISBN
->new($string);
1436 if ( $isbn && $isbn->is_valid() ) {
1438 if ( $format eq 'ISBN-10' ) {
1439 $isbn = $isbn->as_isbn10();
1441 elsif ( $format eq 'ISBN-13' ) {
1442 $isbn = $isbn->as_isbn13();
1444 return unless $isbn;
1446 if ($strip_hyphens) {
1447 $string = $isbn->as_string( [] );
1449 $string = $isbn->as_string();
1456 =head2 GetVariationsOfISBN
1458 my @isbns = GetVariationsOfISBN( $isbn );
1460 Returns a list of variations of the given isbn in
1461 both ISBN-10 and ISBN-13 formats, with and without
1464 In a scalar context, the isbns are returned as a
1465 string delimited by ' | '.
1469 sub GetVariationsOfISBN
{
1472 return unless $isbn;
1476 push( @isbns, NormalizeISBN
({ isbn
=> $isbn }) );
1477 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-10' }) );
1478 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-13' }) );
1479 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-10', strip_hyphens
=> 1 }) );
1480 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-13', strip_hyphens
=> 1 }) );
1482 # Strip out any "empty" strings from the array
1483 @isbns = grep { defined($_) && $_ =~ /\S/ } @isbns;
1485 return wantarray ?
@isbns : join( " | ", @isbns );
1488 =head2 GetVariationsOfISBNs
1490 my @isbns = GetVariationsOfISBNs( @isbns );
1492 Returns a list of variations of the given isbns in
1493 both ISBN-10 and ISBN-13 formats, with and without
1496 In a scalar context, the isbns are returned as a
1497 string delimited by ' | '.
1501 sub GetVariationsOfISBNs
{
1504 @isbns = map { GetVariationsOfISBN
( $_ ) } @isbns;
1506 return wantarray ?
@isbns : join( " | ", @isbns );
1509 =head2 IsKohaFieldLinked
1511 my $is_linked = IsKohaFieldLinked({
1512 kohafield => $kohafield,
1513 frameworkcode => $frameworkcode,
1516 Return 1 if the field is linked
1520 sub IsKohaFieldLinked
{
1521 my ( $params ) = @_;
1522 my $kohafield = $params->{kohafield
};
1523 my $frameworkcode = $params->{frameworkcode
} || '';
1524 my $dbh = C4
::Context
->dbh;
1525 my $is_linked = $dbh->selectcol_arrayref( q
|
1527 FROM marc_subfield_structure
1528 WHERE frameworkcode
= ?
1530 |,{}, $frameworkcode, $kohafield );
1531 return $is_linked->[0];