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
; # Can be removed?
29 use Koha
::DateUtils
qw(dt_from_string);
31 use DateTime
::Format
::MySQL
;
33 use autouse
'Data::cselectall_arrayref' => qw(Dumper);
34 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
56 &get_notforloan_label_of
59 &getitemtypeimagelocation
61 &GetAuthorisedValueCategories
62 &IsAuthorisedValueCategory
63 &GetKohaAuthorisedValues
64 &GetKohaAuthorisedValuesFromField
65 &GetKohaAuthorisedValuesMapping
66 &GetKohaAuthorisedValueLib
67 &GetAuthorisedValueByCode
68 &GetKohaImageurlFromAuthorisedValues
74 &GetNormalizedOCLCNumber
84 @EXPORT_OK = qw( GetDailyQuote );
89 C4::Koha - Perl Module containing convenience functions for Koha scripts
97 Koha.pm provides many functions for Koha scripts.
105 $slash_date = &slashifyDate($dash_date);
107 Takes a string of the form "DD-MM-YYYY" (or anything separated by
108 dashes), converts it to the form "YYYY/MM/DD", and returns the result.
114 # accepts a date of the form xx-xx-xx[xx] and returns it in the
116 my @dateOut = split( '-', shift );
117 return ("$dateOut[2]/$dateOut[1]/$dateOut[0]");
120 # FIXME.. this should be moved to a MARC-specific module
121 sub subfield_is_koha_internal_p
{
124 # We could match on 'lib' and 'tab' (and 'mandatory', & more to come!)
125 # But real MARC subfields are always single-character
126 # so it really is safer just to check the length
128 return length $subfield != 1;
131 =head2 GetSupportName
133 $itemtypename = &GetSupportName($codestring);
135 Returns a string with the name of the itemtype.
141 return if (! $codestring);
143 my $advanced_search_types = C4
::Context
->preference("AdvancedSearchTypes");
144 if (!$advanced_search_types or $advanced_search_types eq 'itemtypes') {
151 my $sth = C4
::Context
->dbh->prepare($query);
152 $sth->execute($codestring);
153 ($resultstring)=$sth->fetchrow;
154 return $resultstring;
157 C4
::Context
->dbh->prepare(
158 "SELECT lib FROM authorised_values WHERE category = ? AND authorised_value = ?"
160 $sth->execute( $advanced_search_types, $codestring );
161 my $data = $sth->fetchrow_hashref;
162 return $$data{'lib'};
166 =head2 GetSupportList
168 $itemtypes = &GetSupportList();
170 Returns an array ref containing informations about Support (since itemtype is rather a circulation code when item-level-itypes is used).
172 build a HTML select with the following code :
174 =head3 in PERL SCRIPT
176 my $itemtypes = GetSupportList();
177 $template->param(itemtypeloop => $itemtypes);
181 <select name="itemtype" id="itemtype">
182 <option value=""></option>
183 [% FOREACH itemtypeloo IN itemtypeloop %]
184 [% IF ( itemtypeloo.selected ) %]
185 <option value="[% itemtypeloo.itemtype %]" selected="selected">[% itemtypeloo.description %]</option>
187 <option value="[% itemtypeloo.itemtype %]">[% itemtypeloo.description %]</option>
195 my $advanced_search_types = C4
::Context
->preference("AdvancedSearchTypes");
196 if (!$advanced_search_types or $advanced_search_types =~ /itemtypes/) {
197 return GetItemTypes
( style
=> 'array' );
199 my $advsearchtypes = GetAuthorisedValues
($advanced_search_types);
200 my @results= map {{itemtype
=>$$_{authorised_value
},description
=>$$_{lib
},imageurl
=>$$_{imageurl
}}} @
$advsearchtypes;
206 $itemtypes = &GetItemTypes( style => $style );
208 Returns information about existing itemtypes.
211 style: either 'array' or 'hash', defaults to 'hash'.
212 'array' returns an arrayref,
213 'hash' return a hashref with the itemtype value as the key
215 build a HTML select with the following code :
217 =head3 in PERL SCRIPT
219 my $itemtypes = GetItemTypes;
221 foreach my $thisitemtype (sort keys %$itemtypes) {
222 my $selected = 1 if $thisitemtype eq $itemtype;
223 my %row =(value => $thisitemtype,
224 selected => $selected,
225 description => $itemtypes->{$thisitemtype}->{'description'},
227 push @itemtypesloop, \%row;
229 $template->param(itemtypeloop => \@itemtypesloop);
233 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
234 <select name="itemtype">
235 <option value="">Default</option>
236 <!-- TMPL_LOOP name="itemtypeloop" -->
237 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="description" --></option>
240 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
241 <input type="submit" value="OK" class="button">
248 my $style = defined( $params{'style'} ) ?
$params{'style'} : 'hash';
250 require C4
::Languages
;
251 my $language = C4
::Languages
::getlanguage
();
252 # returns a reference to a hash of references to itemtypes...
253 my $dbh = C4
::Context
->dbh;
257 itemtypes
.description
,
258 itemtypes
.rentalcharge
,
259 itemtypes
.notforloan
,
262 itemtypes
.checkinmsg
,
263 itemtypes
.checkinmsgtype
,
264 itemtypes
.sip_media_type
,
265 itemtypes
.hideinopac
,
266 itemtypes
.searchcategory
,
267 COALESCE
( localization
.translation
, itemtypes
.description
) AS translated_description
269 LEFT JOIN localization ON itemtypes
.itemtype
= localization
.code
270 AND localization
.entity
= 'itemtypes'
271 AND localization
.lang
= ?
274 my $sth = $dbh->prepare($query);
275 $sth->execute( $language );
277 if ( $style eq 'hash' ) {
279 while ( my $IT = $sth->fetchrow_hashref ) {
280 $itemtypes{ $IT->{'itemtype'} } = $IT;
282 return ( \
%itemtypes );
284 return [ sort { lc $a->{translated_description
} cmp lc $b->{translated_description
} } @
{ $sth->fetchall_arrayref( {} ) } ];
288 =head2 GetItemTypesCategorized
290 $categories = GetItemTypesCategorized();
292 Returns a hashref containing search categories.
293 A search category will be put in the hash if at least one of its itemtypes is visible in OPAC.
294 The categories must be part of Authorized Values (ITEMTYPECAT)
298 sub GetItemTypesCategorized
{
299 my $dbh = C4
::Context
->dbh;
300 # Order is important, so that partially hidden (some items are not visible in OPAC) search
301 # categories will be visible. hideinopac=0 must be last.
303 SELECT itemtype
, description
, imageurl
, hideinopac
, 0 as
'iscat' FROM itemtypes WHERE ISNULL
(searchcategory
) or length(searchcategory
) = 0
305 SELECT DISTINCT searchcategory AS
`itemtype`,
306 authorised_values
.lib_opac AS description
,
307 authorised_values
.imageurl AS imageurl
,
308 hideinopac
, 1 as
'iscat'
310 LEFT JOIN authorised_values ON searchcategory
= authorised_value
311 WHERE searchcategory
> '' and hideinopac
=1
313 SELECT DISTINCT searchcategory AS
`itemtype`,
314 authorised_values
.lib_opac AS description
,
315 authorised_values
.imageurl AS imageurl
,
316 hideinopac
, 1 as
'iscat'
318 LEFT JOIN authorised_values ON searchcategory
= authorised_value
319 WHERE searchcategory
> '' and hideinopac
=0
321 return ($dbh->selectall_hashref($query,'itemtype'));
324 =head2 GetItemTypesByCategory
326 @results = GetItemTypesByCategory( $searchcategory );
328 Returns the itemtype code of all itemtypes included in a searchcategory.
332 sub GetItemTypesByCategory
{
336 my $dbh = C4
::Context
->dbh;
337 my $query = qq|SELECT itemtype FROM itemtypes WHERE searchcategory
=?
|;
338 my $tmp=$dbh->selectcol_arrayref($query,undef,$category);
342 sub get_itemtypeinfos_of
{
345 my $placeholders = join( ', ', map { '?' } @itemtypes );
346 my $query = <<"END_SQL";
352 WHERE itemtype IN ( $placeholders )
355 return get_infos_of( $query, 'itemtype', undef, \@itemtypes );
360 $frameworks = &getframework();
362 Returns information about existing frameworks
364 build a HTML select with the following code :
366 =head3 in PERL SCRIPT
368 my $frameworks = getframeworks();
370 foreach my $thisframework (keys %$frameworks) {
371 my $selected = 1 if $thisframework eq $frameworkcode;
373 value => $thisframework,
374 selected => $selected,
375 description => $frameworks->{$thisframework}->{'frameworktext'},
377 push @frameworksloop, \%row;
379 $template->param(frameworkloop => \@frameworksloop);
383 <form action="[% script_name %] method=post>
384 <select name="frameworkcode">
385 <option value="">Default</option>
386 [% FOREACH framework IN frameworkloop %]
387 [% IF ( framework.selected ) %]
388 <option value="[% framework.value %]" selected="selected">[% framework.description %]</option>
390 <option value="[% framework.value %]">[% framework.description %]</option>
394 <input type
=text name
=searchfield value
="[% searchfield %]">
395 <input type
="submit" value
="OK" class="button">
402 # returns a reference to a hash of references to branches...
404 my $dbh = C4
::Context
->dbh;
405 my $sth = $dbh->prepare("select * from biblio_framework");
407 while ( my $IT = $sth->fetchrow_hashref ) {
408 $itemtypes{ $IT->{'frameworkcode'} } = $IT;
410 return ( \
%itemtypes );
413 =head2 GetFrameworksLoop
415 $frameworks = GetFrameworksLoop( $frameworkcode );
417 Returns the loop suggested on getframework(), but ordered by framework description.
419 build a HTML select with the following code :
421 =head3 in PERL SCRIPT
423 $template->param( frameworkloop => GetFrameworksLoop( $frameworkcode ) );
427 Same as getframework()
429 <form action="[% script_name %] method=post>
430 <select name="frameworkcode">
431 <option value="">Default</option>
432 [% FOREACH framework IN frameworkloop %]
433 [% IF ( framework.selected ) %]
434 <option value="[% framework.value %]" selected="selected">[% framework.description %]</option>
436 <option value="[% framework.value %]">[% framework.description %]</option>
440 <input type=text name=searchfield value="[% searchfield %]">
441 <input type="submit" value="OK" class="button">
446 sub GetFrameworksLoop
{
447 my $frameworkcode = shift;
448 my $frameworks = getframeworks
();
450 foreach my $thisframework (sort { uc($frameworks->{$a}->{'frameworktext'}) cmp uc($frameworks->{$b}->{'frameworktext'}) } keys %$frameworks) {
451 my $selected = ( $thisframework eq $frameworkcode ) ?
1 : undef;
453 value
=> $thisframework,
454 selected
=> $selected,
455 description
=> $frameworks->{$thisframework}->{'frameworktext'},
457 push @frameworkloop, \
%row;
459 return \
@frameworkloop;
462 =head2 getframeworkinfo
464 $frameworkinfo = &getframeworkinfo($frameworkcode);
466 Returns information about an frameworkcode.
470 sub getframeworkinfo
{
471 my ($frameworkcode) = @_;
472 my $dbh = C4
::Context
->dbh;
474 $dbh->prepare("select * from biblio_framework where frameworkcode=?");
475 $sth->execute($frameworkcode);
476 my $res = $sth->fetchrow_hashref;
480 =head2 getitemtypeinfo
482 $itemtype = &getitemtypeinfo($itemtype, [$interface]);
484 Returns information about an itemtype. The optional $interface argument
485 sets which interface ('opac' or 'intranet') to return the imageurl for.
486 Defaults to intranet.
490 sub getitemtypeinfo
{
491 my ($itemtype, $interface) = @_;
492 my $dbh = C4
::Context
->dbh;
493 require C4
::Languages
;
494 my $language = C4
::Languages
::getlanguage
();
495 my $it = $dbh->selectrow_hashref(q
|
498 itemtypes
.description
,
499 itemtypes
.rentalcharge
,
500 itemtypes
.notforloan
,
503 itemtypes
.checkinmsg
,
504 itemtypes
.checkinmsgtype
,
505 itemtypes
.sip_media_type
,
506 COALESCE
( localization
.translation
, itemtypes
.description
) AS translated_description
508 LEFT JOIN localization ON itemtypes
.itemtype
= localization
.code
509 AND localization
.entity
= 'itemtypes'
510 AND localization
.lang
= ?
511 WHERE itemtypes
.itemtype
= ?
512 |, undef, $language, $itemtype );
514 $it->{imageurl
} = getitemtypeimagelocation
( ( ( defined $interface && $interface eq 'opac' ) ?
'opac' : 'intranet' ), $it->{imageurl
} );
519 =head2 getitemtypeimagedir
521 my $directory = getitemtypeimagedir( 'opac' );
523 pass in 'opac' or 'intranet'. Defaults to 'opac'.
525 returns the full path to the appropriate directory containing images.
529 sub getitemtypeimagedir
{
530 my $src = shift || 'opac';
531 if ($src eq 'intranet') {
532 return C4
::Context
->config('intrahtdocs') . '/' .C4
::Context
->preference('template') . '/img/itemtypeimg';
534 return C4
::Context
->config('opachtdocs') . '/' . C4
::Context
->preference('opacthemes') . '/itemtypeimg';
538 sub getitemtypeimagesrc
{
539 my $src = shift || 'opac';
540 if ($src eq 'intranet') {
541 return '/intranet-tmpl' . '/' . C4
::Context
->preference('template') . '/img/itemtypeimg';
543 return '/opac-tmpl' . '/' . C4
::Context
->preference('opacthemes') . '/itemtypeimg';
547 sub getitemtypeimagelocation
{
548 my ( $src, $image ) = @_;
550 return '' if ( !$image );
553 my $scheme = ( URI
::Split
::uri_split
( $image ) )[0];
555 return $image if ( $scheme );
557 return getitemtypeimagesrc
( $src ) . '/' . $image;
560 =head3 _getImagesFromDirectory
562 Find all of the image files in a directory in the filesystem
564 parameters: a directory name
566 returns: a list of images in that directory.
568 Notes: this does not traverse into subdirectories. See
569 _getSubdirectoryNames for help with that.
570 Images are assumed to be files with .gif or .png file extensions.
571 The image names returned do not have the directory name on them.
575 sub _getImagesFromDirectory
{
576 my $directoryname = shift;
577 return unless defined $directoryname;
578 return unless -d
$directoryname;
580 if ( opendir ( my $dh, $directoryname ) ) {
581 my @images = grep { /\.(gif|png)$/i } readdir( $dh );
583 @images = sort(@images);
586 warn "unable to opendir $directoryname: $!";
591 =head3 _getSubdirectoryNames
593 Find all of the directories in a directory in the filesystem
595 parameters: a directory name
597 returns: a list of subdirectories in that directory.
599 Notes: this does not traverse into subdirectories. Only the first
600 level of subdirectories are returned.
601 The directory names returned don't have the parent directory name on them.
605 sub _getSubdirectoryNames
{
606 my $directoryname = shift;
607 return unless defined $directoryname;
608 return unless -d
$directoryname;
610 if ( opendir ( my $dh, $directoryname ) ) {
611 my @directories = grep { -d File
::Spec
->catfile( $directoryname, $_ ) && ! ( /^\./ ) } readdir( $dh );
615 warn "unable to opendir $directoryname: $!";
622 returns: a listref of hashrefs. Each hash represents another collection of images.
624 { imagesetname => 'npl', # the name of the image set (npl is the original one)
625 images => listref of image hashrefs
628 each image is represented by a hashref like this:
630 { KohaImage => 'npl/image.gif',
631 StaffImageUrl => '/intranet-tmpl/prog/img/itemtypeimg/npl/image.gif',
632 OpacImageURL => '/opac-tmpl/prog/itemtypeimg/npl/image.gif'
633 checked => 0 or 1: was this the image passed to this method?
634 Note: I'd like to remove this somehow.
641 my $checked = $params{'checked'} || '';
643 my $paths = { staff
=> { filesystem
=> getitemtypeimagedir
('intranet'),
644 url
=> getitemtypeimagesrc
('intranet'),
646 opac
=> { filesystem
=> getitemtypeimagedir
('opac'),
647 url
=> getitemtypeimagesrc
('opac'),
651 my @imagesets = (); # list of hasrefs of image set data to pass to template
652 my @subdirectories = _getSubdirectoryNames
( $paths->{'staff'}{'filesystem'} );
653 foreach my $imagesubdir ( @subdirectories ) {
654 warn $imagesubdir if $DEBUG;
655 my @imagelist = (); # hashrefs of image info
656 my @imagenames = _getImagesFromDirectory
( File
::Spec
->catfile( $paths->{'staff'}{'filesystem'}, $imagesubdir ) );
657 my $imagesetactive = 0;
658 foreach my $thisimage ( @imagenames ) {
660 { KohaImage
=> "$imagesubdir/$thisimage",
661 StaffImageUrl
=> join( '/', $paths->{'staff'}{'url'}, $imagesubdir, $thisimage ),
662 OpacImageUrl
=> join( '/', $paths->{'opac'}{'url'}, $imagesubdir, $thisimage ),
663 checked
=> "$imagesubdir/$thisimage" eq $checked ?
1 : 0,
666 $imagesetactive = 1 if "$imagesubdir/$thisimage" eq $checked;
668 push @imagesets, { imagesetname
=> $imagesubdir,
669 imagesetactive
=> $imagesetactive,
670 images
=> \
@imagelist };
678 $printers = &GetPrinters();
679 @queues = keys %$printers;
681 Returns information about existing printer queues.
683 C<$printers> is a reference-to-hash whose keys are the print queues
684 defined in the printers table of the Koha database. The values are
685 references-to-hash, whose keys are the fields in the printers table.
691 my $dbh = C4
::Context
->dbh;
692 my $sth = $dbh->prepare("select * from printers");
694 while ( my $printer = $sth->fetchrow_hashref ) {
695 $printers{ $printer->{'printqueue'} } = $printer;
697 return ( \
%printers );
702 $printer = GetPrinter( $query, $printers );
707 my ( $query, $printers ) = @_; # get printer for this query from printers
708 my $printer = $query->param('printer');
709 my %cookie = $query->cookie('userenv');
710 ($printer) || ( $printer = $cookie{'printer'} ) || ( $printer = '' );
711 ( $printers->{$printer} ) || ( $printer = ( keys %$printers )[0] );
717 Returns the number of pages to display in a pagination bar, given the number
718 of items and the number of items per page.
723 my ( $nb_items, $nb_items_per_page ) = @_;
725 return int( ( $nb_items - 1 ) / $nb_items_per_page ) + 1;
730 (@themes) = &getallthemes('opac');
731 (@themes) = &getallthemes('intranet');
733 Returns an array of all available themes.
741 if ( $type eq 'intranet' ) {
742 $htdocs = C4
::Context
->config('intrahtdocs');
745 $htdocs = C4
::Context
->config('opachtdocs');
747 opendir D
, "$htdocs";
748 my @dirlist = readdir D
;
749 foreach my $directory (@dirlist) {
750 next if $directory eq 'lib';
751 -d
"$htdocs/$directory/en" and push @themes, $directory;
758 if ( C4
::Context
->preference("marcflavour") eq "UNIMARC" ) {
763 tags
=> [ qw
/ 600ab 601ab 602a 604at 605a 606ax 610a / ],
769 tags
=> [ qw
/ 607a / ],
775 tags
=> [ qw
/ 500a 501a 503a / ],
781 tags
=> [ qw
/ 700ab 701ab 702ab / ],
782 sep
=> C4
::Context
->preference("UNIMARCAuthorsFacetsSeparator"),
787 tags
=> [ qw
/ 225a / ],
793 tags
=> [ qw
/ 995e / ],
797 unless ( C4
::Context
->preference("singleBranchMode")
798 || Koha
::Libraries
->search->count == 1 )
800 my $DisplayLibraryFacets = C4
::Context
->preference('DisplayLibraryFacets');
801 if ( $DisplayLibraryFacets eq 'both'
802 || $DisplayLibraryFacets eq 'holding' )
807 idx
=> 'holdingbranch',
808 label
=> 'HoldingLibrary',
809 tags
=> [qw
/ 995c /],
814 if ( $DisplayLibraryFacets eq 'both'
815 || $DisplayLibraryFacets eq 'home' )
821 label
=> 'HomeLibrary',
822 tags
=> [qw
/ 995b /],
833 tags
=> [ qw
/ 650a / ],
838 # label => 'People and Organizations',
839 # tags => [ qw/ 600a 610a 611a / ],
845 tags
=> [ qw
/ 651a / ],
851 tags
=> [ qw
/ 630a / ],
857 tags
=> [ qw
/ 100a 110a 700a / ],
863 tags
=> [ qw
/ 440a 490a / ],
868 label
=> 'ItemTypes',
869 tags
=> [ qw
/ 952y 942c / ],
875 tags
=> [ qw
/ 952c / ],
879 unless ( C4
::Context
->preference("singleBranchMode")
880 || Koha
::Libraries
->search->count == 1 )
882 my $DisplayLibraryFacets = C4
::Context
->preference('DisplayLibraryFacets');
883 if ( $DisplayLibraryFacets eq 'both'
884 || $DisplayLibraryFacets eq 'holding' )
889 idx
=> 'holdingbranch',
890 label
=> 'HoldingLibrary',
891 tags
=> [qw
/ 952b /],
896 if ( $DisplayLibraryFacets eq 'both'
897 || $DisplayLibraryFacets eq 'home' )
903 label
=> 'HomeLibrary',
904 tags
=> [qw
/ 952a /],
915 Return a href where a key is associated to a href. You give a query,
916 the name of the key among the fields returned by the query. If you
917 also give as third argument the name of the value, the function
918 returns a href of scalar. The optional 4th argument is an arrayref of
919 items passed to the C<execute()> call. It is designed to bind
920 parameters to any placeholders in your SQL.
929 # generic href of any information on the item, href of href.
930 my $iteminfos_of = get_infos_of($query, 'itemnumber');
931 print $iteminfos_of->{$itemnumber}{barcode};
933 # specific information, href of scalar
934 my $barcode_of_item = get_infos_of($query, 'itemnumber', 'barcode');
935 print $barcode_of_item->{$itemnumber};
940 my ( $query, $key_name, $value_name, $bind_params ) = @_;
942 my $dbh = C4
::Context
->dbh;
944 my $sth = $dbh->prepare($query);
945 $sth->execute( @
$bind_params );
948 while ( my $row = $sth->fetchrow_hashref ) {
949 if ( defined $value_name ) {
950 $infos_of{ $row->{$key_name} } = $row->{$value_name};
953 $infos_of{ $row->{$key_name} } = $row;
961 =head2 get_notforloan_label_of
963 my $notforloan_label_of = get_notforloan_label_of();
965 Each authorised value of notforloan (information available in items and
966 itemtypes) is link to a single label.
968 Returns a href where keys are authorised values and values are corresponding
971 foreach my $authorised_value (keys %{$notforloan_label_of}) {
973 "authorised_value: %s => %s\n",
975 $notforloan_label_of->{$authorised_value}
981 # FIXME - why not use GetAuthorisedValues ??
983 sub get_notforloan_label_of
{
984 my $dbh = C4
::Context
->dbh;
987 SELECT authorised_value
988 FROM marc_subfield_structure
989 WHERE kohafield = \'items.notforloan\'
992 my $sth = $dbh->prepare($query);
994 my ($statuscode) = $sth->fetchrow_array();
999 FROM authorised_values
1002 $sth = $dbh->prepare($query);
1003 $sth->execute($statuscode);
1004 my %notforloan_label_of;
1005 while ( my $row = $sth->fetchrow_hashref ) {
1006 $notforloan_label_of{ $row->{authorised_value
} } = $row->{lib
};
1010 return \
%notforloan_label_of;
1013 =head2 displayServers
1015 my $servers = displayServers();
1016 my $servers = displayServers( $position );
1017 my $servers = displayServers( $position, $type );
1019 displayServers returns a listref of hashrefs, each containing
1020 information about available z3950 servers. Each hashref has a format
1024 'checked' => 'checked',
1025 'encoding' => 'utf8',
1027 'id' => 'LIBRARY OF CONGRESS',
1031 'value' => 'lx2.loc.gov:210/',
1037 sub displayServers
{
1038 my ( $position, $type ) = @_;
1039 my $dbh = C4
::Context
->dbh;
1041 my $strsth = 'SELECT * FROM z3950servers';
1046 push @bind_params, $position;
1047 push @where_clauses, ' position = ? ';
1051 push @bind_params, $type;
1052 push @where_clauses, ' type = ? ';
1055 # reassemble where clause from where clause pieces
1056 if (@where_clauses) {
1057 $strsth .= ' WHERE ' . join( ' AND ', @where_clauses );
1060 my $rq = $dbh->prepare($strsth);
1061 $rq->execute(@bind_params);
1062 my @primaryserverloop;
1064 while ( my $data = $rq->fetchrow_hashref ) {
1065 push @primaryserverloop,
1066 { label
=> $data->{description
},
1067 id
=> $data->{name
},
1069 value
=> $data->{host
} . ":" . $data->{port
} . "/" . $data->{database
},
1070 encoding
=> ( $data->{encoding
} ?
$data->{encoding
} : "iso-5426" ),
1071 checked
=> "checked",
1072 icon
=> $data->{icon
},
1073 zed
=> $data->{type
} eq 'zed',
1074 opensearch
=> $data->{type
} eq 'opensearch'
1077 return \
@primaryserverloop;
1081 =head2 GetKohaImageurlFromAuthorisedValues
1083 $authhorised_value = GetKohaImageurlFromAuthorisedValues( $category, $authvalcode );
1085 Return the first url of the authorised value image represented by $lib.
1089 sub GetKohaImageurlFromAuthorisedValues
{
1090 my ( $category, $lib ) = @_;
1091 my $dbh = C4
::Context
->dbh;
1092 my $sth = $dbh->prepare("SELECT imageurl FROM authorised_values WHERE category=? AND lib =?");
1093 $sth->execute( $category, $lib );
1094 while ( my $data = $sth->fetchrow_hashref ) {
1095 return $data->{'imageurl'};
1099 =head2 GetAuthValCode
1101 $authvalcode = GetAuthValCode($kohafield,$frameworkcode);
1105 sub GetAuthValCode
{
1106 my ($kohafield,$fwcode) = @_;
1107 my $dbh = C4
::Context
->dbh;
1108 $fwcode='' unless $fwcode;
1109 my $sth = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield=? and frameworkcode=?');
1110 $sth->execute($kohafield,$fwcode);
1111 my ($authvalcode) = $sth->fetchrow_array;
1112 return $authvalcode;
1115 =head2 GetAuthValCodeFromField
1117 $authvalcode = GetAuthValCodeFromField($field,$subfield,$frameworkcode);
1119 C<$subfield> can be undefined
1123 sub GetAuthValCodeFromField
{
1124 my ($field,$subfield,$fwcode) = @_;
1125 my $dbh = C4
::Context
->dbh;
1126 $fwcode='' unless $fwcode;
1128 if (defined $subfield) {
1129 $sth = $dbh->prepare('select authorised_value from marc_subfield_structure where tagfield=? and tagsubfield=? and frameworkcode=?');
1130 $sth->execute($field,$subfield,$fwcode);
1132 $sth = $dbh->prepare('select authorised_value from marc_tag_structure where tagfield=? and frameworkcode=?');
1133 $sth->execute($field,$fwcode);
1135 my ($authvalcode) = $sth->fetchrow_array;
1136 return $authvalcode;
1139 =head2 GetAuthorisedValues
1141 $authvalues = GetAuthorisedValues([$category], [$selected]);
1143 This function returns all authorised values from the'authorised_value' table in a reference to array of hashrefs.
1145 C<$category> returns authorised values for just one category (optional).
1147 C<$selected> adds a "selected => 1" entry to the hash if the
1148 authorised_value matches it. B<NOTE:> this feature should be considered
1149 deprecated as it may be removed in the future.
1151 C<$opac> If set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1155 sub GetAuthorisedValues
{
1156 my ( $category, $selected, $opac ) = @_;
1158 # TODO: the "selected" feature should be replaced by a utility function
1159 # somewhere else, it doesn't belong in here. For starters it makes
1160 # caching much more complicated. Or just let the UI logic handle it, it's
1163 # Is this cached already?
1164 $opac = $opac ?
1 : 0; # normalise to be safe
1166 C4
::Context
->userenv ? C4
::Context
->userenv->{"branch"} : "";
1167 my $selected_key = defined($selected) ?
$selected : '';
1169 "AuthorisedValues-$category-$selected_key-$opac-$branch_limit";
1170 my $cache = Koha
::Cache
->get_instance();
1171 my $result = $cache->get_from_cache($cache_key);
1172 return $result if $result;
1175 my $dbh = C4
::Context
->dbh;
1178 FROM authorised_values
1181 LEFT JOIN authorised_values_branches ON
( id
= av_id
)
1186 push @where_strings, "category = ?";
1187 push @where_args, $category;
1190 push @where_strings, "( branchcode = ? OR branchcode IS NULL )";
1191 push @where_args, $branch_limit;
1193 if(@where_strings > 0) {
1194 $query .= " WHERE " . join(" AND ", @where_strings);
1196 $query .= " GROUP BY lib";
1197 $query .= ' ORDER BY category, ' . (
1198 $opac ?
'COALESCE(lib_opac, lib)'
1202 my $sth = $dbh->prepare($query);
1204 $sth->execute( @where_args );
1205 while (my $data=$sth->fetchrow_hashref) {
1206 if ( defined $selected and $selected eq $data->{authorised_value
} ) {
1207 $data->{selected
} = 1;
1210 $data->{selected
} = 0;
1213 if ($opac && $data->{lib_opac
}) {
1214 $data->{lib
} = $data->{lib_opac
};
1216 push @results, $data;
1220 # We can't cache for long because of that "selected" thing which
1221 # makes it impossible to clear the cache without iterating through every
1222 # value, which sucks. This'll cover this request, and not a whole lot more.
1223 $cache->set_in_cache( $cache_key, \
@results, { deepcopy
=> 1, expiry
=> 5 } );
1227 =head2 GetAuthorisedValueCategories
1229 $auth_categories = GetAuthorisedValueCategories();
1231 Return an arrayref of all of the available authorised
1236 sub GetAuthorisedValueCategories
{
1237 my $dbh = C4
::Context
->dbh;
1238 my $sth = $dbh->prepare("SELECT DISTINCT category FROM authorised_values ORDER BY category");
1241 while (defined (my $category = $sth->fetchrow_array) ) {
1242 push @results, $category;
1247 =head2 IsAuthorisedValueCategory
1249 $is_auth_val_category = IsAuthorisedValueCategory($category);
1251 Returns whether a given category name is a valid one
1255 sub IsAuthorisedValueCategory
{
1256 my $category = shift;
1259 FROM authorised_values
1263 my $sth = C4
::Context
->dbh->prepare($query);
1264 $sth->execute($category);
1265 $sth->fetchrow ?
return 1
1269 =head2 GetAuthorisedValueByCode
1271 $authorised_value = GetAuthorisedValueByCode( $category, $authvalcode, $opac );
1273 Return the lib attribute from authorised_values from the row identified
1274 by the passed category and code
1278 sub GetAuthorisedValueByCode
{
1279 my ( $category, $authvalcode, $opac ) = @_;
1281 my $field = $opac ?
'lib_opac' : 'lib';
1282 my $dbh = C4
::Context
->dbh;
1283 my $sth = $dbh->prepare("SELECT $field FROM authorised_values WHERE category=? AND authorised_value =?");
1284 $sth->execute( $category, $authvalcode );
1285 while ( my $data = $sth->fetchrow_hashref ) {
1286 return $data->{ $field };
1290 =head2 GetKohaAuthorisedValues
1292 Takes $kohafield, $fwcode as parameters.
1294 If $opac parameter is set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1296 Returns hashref of Code => description
1298 Returns undef if no authorised value category is defined for the kohafield.
1302 sub GetKohaAuthorisedValues
{
1303 my ($kohafield,$fwcode,$opac) = @_;
1304 $fwcode='' unless $fwcode;
1306 my $dbh = C4
::Context
->dbh;
1307 my $avcode = GetAuthValCode
($kohafield,$fwcode);
1309 my $sth = $dbh->prepare("select authorised_value, lib, lib_opac from authorised_values where category=? ");
1310 $sth->execute($avcode);
1311 while ( my ($val, $lib, $lib_opac) = $sth->fetchrow_array ) {
1312 $values{$val} = ($opac && $lib_opac) ?
$lib_opac : $lib;
1320 =head2 GetKohaAuthorisedValuesFromField
1322 Takes $field, $subfield, $fwcode as parameters.
1324 If $opac parameter is set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1325 $subfield can be undefined
1327 Returns hashref of Code => description
1329 Returns undef if no authorised value category is defined for the given field and subfield
1333 sub GetKohaAuthorisedValuesFromField
{
1334 my ($field, $subfield, $fwcode,$opac) = @_;
1335 $fwcode='' unless $fwcode;
1337 my $dbh = C4
::Context
->dbh;
1338 my $avcode = GetAuthValCodeFromField
($field, $subfield, $fwcode);
1340 my $sth = $dbh->prepare("select authorised_value, lib, lib_opac from authorised_values where category=? ");
1341 $sth->execute($avcode);
1342 while ( my ($val, $lib, $lib_opac) = $sth->fetchrow_array ) {
1343 $values{$val} = ($opac && $lib_opac) ?
$lib_opac : $lib;
1351 =head2 GetKohaAuthorisedValuesMapping
1353 Takes a hash as a parameter. The interface key indicates the
1354 description to use in the mapping.
1357 "{kohafield},{frameworkcode},{authorised_value}" => "{description}"
1358 for all the kohafields, frameworkcodes, and authorised values.
1360 Returns undef if nothing is found.
1364 sub GetKohaAuthorisedValuesMapping
{
1365 my ($parameter) = @_;
1366 my $interface = $parameter->{'interface'} // '';
1368 my $query_mapping = q{
1369 SELECT TA.kohafield,TA.authorised_value AS category,
1370 TA.frameworkcode,TB.authorised_value,
1371 IF(TB.lib_opac>'',TB.lib_opac,TB.lib) AS OPAC,
1372 TB.lib AS Intranet,TB.lib_opac
1373 FROM marc_subfield_structure AS TA JOIN
1374 authorised_values as TB ON
1375 TA.authorised_value=TB.category
1376 WHERE TA.kohafield>'' AND TA.authorised_value>'';
1378 my $dbh = C4
::Context
->dbh;
1379 my $sth = $dbh->prepare($query_mapping);
1382 if ($interface eq 'opac') {
1383 while (my $row = $sth->fetchrow_hashref) {
1384 $avmapping->{$row->{kohafield
}.",".$row->{frameworkcode
}.",".$row->{authorised_value
}} = $row->{OPAC
};
1388 while (my $row = $sth->fetchrow_hashref) {
1389 $avmapping->{$row->{kohafield
}.",".$row->{frameworkcode
}.",".$row->{authorised_value
}} = $row->{Intranet
};
1397 my $escaped_string = C4::Koha::xml_escape($string);
1399 Convert &, <, >, ', and " in a string to XML entities
1405 return '' unless defined $str;
1406 $str =~ s/&/&/g;
1409 $str =~ s/'/'/g;
1410 $str =~ s/"/"/g;
1414 =head2 GetKohaAuthorisedValueLib
1416 Takes $category, $authorised_value as parameters.
1418 If $opac parameter is set to a true value, displays OPAC descriptions rather than normal ones when they exist.
1420 Returns authorised value description
1424 sub GetKohaAuthorisedValueLib
{
1425 my ($category,$authorised_value,$opac) = @_;
1427 my $dbh = C4
::Context
->dbh;
1428 my $sth = $dbh->prepare("select lib, lib_opac from authorised_values where category=? and authorised_value=?");
1429 $sth->execute($category,$authorised_value);
1430 my $data = $sth->fetchrow_hashref;
1431 $value = ($opac && $$data{'lib_opac'}) ?
$$data{'lib_opac'} : $$data{'lib'};
1435 =head2 AddAuthorisedValue
1437 AddAuthorisedValue($category, $authorised_value, $lib, $lib_opac, $imageurl);
1439 Create a new authorised value.
1443 sub AddAuthorisedValue
{
1444 my ($category, $authorised_value, $lib, $lib_opac, $imageurl) = @_;
1446 my $dbh = C4
::Context
->dbh;
1448 INSERT INTO authorised_values
(category
, authorised_value
, lib
, lib_opac
, imageurl
)
1451 my $sth = $dbh->prepare($query);
1452 $sth->execute($category, $authorised_value, $lib, $lib_opac, $imageurl);
1455 =head2 display_marc_indicators
1457 my $display_form = C4::Koha::display_marc_indicators($field);
1459 C<$field> is a MARC::Field object
1461 Generate a display form of the indicators of a variable
1462 MARC field, replacing any blanks with '#'.
1466 sub display_marc_indicators
{
1468 my $indicators = '';
1469 if ($field && $field->tag() >= 10) {
1470 $indicators = $field->indicator(1) . $field->indicator(2);
1471 $indicators =~ s/ /#/g;
1476 sub GetNormalizedUPC
{
1477 my ($marcrecord,$marcflavour) = @_;
1479 return unless $marcrecord;
1480 if ($marcflavour eq 'UNIMARC') {
1481 my @fields = $marcrecord->field('072');
1482 foreach my $field (@fields) {
1483 my $upc = _normalize_match_point
($field->subfield('a'));
1490 else { # assume marc21 if not unimarc
1491 my @fields = $marcrecord->field('024');
1492 foreach my $field (@fields) {
1493 my $indicator = $field->indicator(1);
1494 my $upc = _normalize_match_point
($field->subfield('a'));
1495 if ($upc && $indicator == 1 ) {
1502 # Normalizes and returns the first valid ISBN found in the record
1503 # ISBN13 are converted into ISBN10. This is required to get some book cover images.
1504 sub GetNormalizedISBN
{
1505 my ($isbn,$marcrecord,$marcflavour) = @_;
1507 # Koha attempts to store multiple ISBNs in biblioitems.isbn, separated by " | "
1508 # anything after " | " should be removed, along with the delimiter
1509 ($isbn) = split(/\|/, $isbn );
1510 return _isbn_cleanup
($isbn);
1513 return unless $marcrecord;
1515 if ($marcflavour eq 'UNIMARC') {
1516 my @fields = $marcrecord->field('010');
1517 foreach my $field (@fields) {
1518 my $isbn = $field->subfield('a');
1520 return _isbn_cleanup
($isbn);
1524 else { # assume marc21 if not unimarc
1525 my @fields = $marcrecord->field('020');
1526 foreach my $field (@fields) {
1527 $isbn = $field->subfield('a');
1529 return _isbn_cleanup
($isbn);
1535 sub GetNormalizedEAN
{
1536 my ($marcrecord,$marcflavour) = @_;
1538 return unless $marcrecord;
1540 if ($marcflavour eq 'UNIMARC') {
1541 my @fields = $marcrecord->field('073');
1542 foreach my $field (@fields) {
1543 my $ean = _normalize_match_point
($field->subfield('a'));
1549 else { # assume marc21 if not unimarc
1550 my @fields = $marcrecord->field('024');
1551 foreach my $field (@fields) {
1552 my $indicator = $field->indicator(1);
1553 my $ean = _normalize_match_point
($field->subfield('a'));
1554 if ( $ean && $indicator == 3 ) {
1561 sub GetNormalizedOCLCNumber
{
1562 my ($marcrecord,$marcflavour) = @_;
1563 return unless $marcrecord;
1565 if ($marcflavour ne 'UNIMARC' ) {
1566 my @fields = $marcrecord->field('035');
1567 foreach my $field (@fields) {
1568 my $oclc = $field->subfield('a');
1569 if ($oclc =~ /OCoLC/) {
1570 $oclc =~ s/\(OCoLC\)//;
1580 sub GetAuthvalueDropbox
{
1581 my ( $authcat, $default ) = @_;
1582 my $branch_limit = C4
::Context
->userenv ? C4
::Context
->userenv->{"branch"} : "";
1583 my $dbh = C4
::Context
->dbh;
1587 FROM authorised_values
1590 LEFT JOIN authorised_values_branches ON
( id
= av_id
)
1595 $query .= " AND ( branchcode = ? OR branchcode IS NULL )" if $branch_limit;
1596 $query .= " GROUP BY lib ORDER BY category, lib, lib_opac";
1597 my $sth = $dbh->prepare($query);
1598 $sth->execute( $authcat, $branch_limit ?
$branch_limit : () );
1601 my $option_list = [];
1602 my @authorised_values = ( q{} );
1603 while (my $av = $sth->fetchrow_hashref) {
1604 push @
{$option_list}, {
1605 value
=> $av->{authorised_value
},
1606 label
=> $av->{lib
},
1607 default => ($default eq $av->{authorised_value
}),
1611 if ( @
{$option_list} ) {
1612 return $option_list;
1618 =head2 GetDailyQuote($opts)
1620 Takes a hashref of options
1622 Currently supported options are:
1624 'id' An exact quote id
1625 'random' Select a random quote
1626 noop When no option is passed in, this sub will return the quote timestamped for the current day
1628 The function returns an anonymous hash following this format:
1631 'source' => 'source-of-quote',
1632 'timestamp' => 'timestamp-value',
1633 'text' => 'text-of-quote',
1639 # This is definitely a candidate for some sort of caching once we finally settle caching/persistence issues...
1640 # at least for default option
1644 my $dbh = C4
::Context
->dbh;
1649 $query = 'SELECT * FROM quotes WHERE id = ?';
1650 $sth = $dbh->prepare($query);
1651 $sth->execute($opts{'id'});
1652 $quote = $sth->fetchrow_hashref();
1654 elsif ($opts{'random'}) {
1655 # Fall through... we also return a random quote as a catch-all if all else fails
1658 $query = 'SELECT * FROM quotes WHERE timestamp LIKE CONCAT(CURRENT_DATE,\'%\') ORDER BY timestamp DESC LIMIT 0,1';
1659 $sth = $dbh->prepare($query);
1661 $quote = $sth->fetchrow_hashref();
1663 unless ($quote) { # if there are not matches, choose a random quote
1664 # get a list of all available quote ids
1665 $sth = C4
::Context
->dbh->prepare('SELECT count(*) FROM quotes;');
1667 my $range = ($sth->fetchrow_array)[0];
1668 # chose a random id within that range if there is more than one quote
1669 my $offset = int(rand($range));
1671 $query = 'SELECT * FROM quotes ORDER BY id LIMIT 1 OFFSET ?';
1672 $sth = C4
::Context
->dbh->prepare($query);
1673 # see http://www.perlmonks.org/?node_id=837422 for why
1674 # we're being verbose and using bind_param
1675 $sth->bind_param(1, $offset, SQL_INTEGER
);
1677 $quote = $sth->fetchrow_hashref();
1678 # update the timestamp for that quote
1679 $query = 'UPDATE quotes SET timestamp = ? WHERE id = ?';
1680 $sth = C4
::Context
->dbh->prepare($query);
1682 DateTime
::Format
::MySQL
->format_datetime( dt_from_string
() ),
1689 sub _normalize_match_point
{
1690 my $match_point = shift;
1691 (my $normalized_match_point) = $match_point =~ /([\d-]*[X]*)/;
1692 $normalized_match_point =~ s/-//g;
1694 return $normalized_match_point;
1699 return NormalizeISBN
(
1702 format
=> 'ISBN-10',
1708 =head2 NormalizedISBN
1710 my $isbns = NormalizedISBN({
1712 strip_hyphens => [0,1],
1713 format => ['ISBN-10', 'ISBN-13']
1716 Returns an isbn validated by Business::ISBN.
1717 Optionally strips hyphens and/or forces the isbn
1718 to be of the specified format.
1720 If the string cannot be validated as an isbn,
1728 my $string = $params->{isbn
};
1729 my $strip_hyphens = $params->{strip_hyphens
};
1730 my $format = $params->{format
};
1732 return unless $string;
1734 my $isbn = Business
::ISBN
->new($string);
1736 if ( $isbn && $isbn->is_valid() ) {
1738 if ( $format eq 'ISBN-10' ) {
1739 $isbn = $isbn->as_isbn10();
1741 elsif ( $format eq 'ISBN-13' ) {
1742 $isbn = $isbn->as_isbn13();
1744 return unless $isbn;
1746 if ($strip_hyphens) {
1747 $string = $isbn->as_string( [] );
1749 $string = $isbn->as_string();
1756 =head2 GetVariationsOfISBN
1758 my @isbns = GetVariationsOfISBN( $isbn );
1760 Returns a list of variations of the given isbn in
1761 both ISBN-10 and ISBN-13 formats, with and without
1764 In a scalar context, the isbns are returned as a
1765 string delimited by ' | '.
1769 sub GetVariationsOfISBN
{
1772 return unless $isbn;
1776 push( @isbns, NormalizeISBN
({ isbn
=> $isbn }) );
1777 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-10' }) );
1778 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-13' }) );
1779 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-10', strip_hyphens
=> 1 }) );
1780 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-13', strip_hyphens
=> 1 }) );
1782 # Strip out any "empty" strings from the array
1783 @isbns = grep { defined($_) && $_ =~ /\S/ } @isbns;
1785 return wantarray ?
@isbns : join( " | ", @isbns );
1788 =head2 GetVariationsOfISBNs
1790 my @isbns = GetVariationsOfISBNs( @isbns );
1792 Returns a list of variations of the given isbns in
1793 both ISBN-10 and ISBN-13 formats, with and without
1796 In a scalar context, the isbns are returned as a
1797 string delimited by ' | '.
1801 sub GetVariationsOfISBNs
{
1804 @isbns = map { GetVariationsOfISBN
( $_ ) } @isbns;
1806 return wantarray ?
@isbns : join( " | ", @isbns );
1809 =head2 IsKohaFieldLinked
1811 my $is_linked = IsKohaFieldLinked({
1812 kohafield => $kohafield,
1813 frameworkcode => $frameworkcode,
1816 Return 1 if the field is linked
1820 sub IsKohaFieldLinked
{
1821 my ( $params ) = @_;
1822 my $kohafield = $params->{kohafield
};
1823 my $frameworkcode = $params->{frameworkcode
} || '';
1824 my $dbh = C4
::Context
->dbh;
1825 my $is_linked = $dbh->selectcol_arrayref( q
|
1827 FROM marc_subfield_structure
1828 WHERE frameworkcode
= ?
1830 |,{}, $frameworkcode, $kohafield );
1831 return $is_linked->[0];