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);
29 use Koha
::AuthorisedValues
;
31 use Koha
::MarcSubfieldStructures
;
32 use DateTime
::Format
::MySQL
;
35 use autouse
'Data::cselectall_arrayref' => qw(Dumper);
36 use DBI
qw(:sql_types);
37 use vars
qw(@ISA @EXPORT @EXPORT_OK $DEBUG);
43 &GetPrinters &GetPrinter
44 &GetItemTypes &getitemtypeinfo
45 &GetItemTypesCategorized &GetItemTypesByCategory
50 &get_notforloan_label_of
53 &getitemtypeimagelocation
58 &GetNormalizedOCLCNumber
71 @EXPORT_OK = qw( GetDailyQuote );
76 C4::Koha - Perl Module containing convenience functions for Koha scripts
84 Koha.pm provides many functions for Koha scripts.
92 $itemtypes = &GetItemTypes( style => $style );
94 Returns information about existing itemtypes.
97 style: either 'array' or 'hash', defaults to 'hash'.
98 'array' returns an arrayref,
99 'hash' return a hashref with the itemtype value as the key
101 build a HTML select with the following code :
103 =head3 in PERL SCRIPT
105 my $itemtypes = GetItemTypes;
107 foreach my $thisitemtype (sort keys %$itemtypes) {
108 my $selected = 1 if $thisitemtype eq $itemtype;
109 my %row =(value => $thisitemtype,
110 selected => $selected,
111 description => $itemtypes->{$thisitemtype}->{'description'},
113 push @itemtypesloop, \%row;
115 $template->param(itemtypeloop => \@itemtypesloop);
119 <form action='<!-- TMPL_VAR name="script_name" -->' method=post>
120 <select name="itemtype">
121 <option value="">Default</option>
122 <!-- TMPL_LOOP name="itemtypeloop" -->
123 <option value="<!-- TMPL_VAR name="value" -->" <!-- TMPL_IF name="selected" -->selected<!-- /TMPL_IF -->><!-- TMPL_VAR name="description" --></option>
126 <input type=text name=searchfield value="<!-- TMPL_VAR name="searchfield" -->">
127 <input type="submit" value="OK" class="button">
134 my $style = defined( $params{'style'} ) ?
$params{'style'} : 'hash';
136 require C4
::Languages
;
137 my $language = C4
::Languages
::getlanguage
();
138 # returns a reference to a hash of references to itemtypes...
139 my $dbh = C4
::Context
->dbh;
143 itemtypes
.description
,
144 itemtypes
.rentalcharge
,
145 itemtypes
.notforloan
,
148 itemtypes
.checkinmsg
,
149 itemtypes
.checkinmsgtype
,
150 itemtypes
.sip_media_type
,
151 itemtypes
.hideinopac
,
152 itemtypes
.searchcategory
,
153 COALESCE
( localization
.translation
, itemtypes
.description
) AS translated_description
155 LEFT JOIN localization ON itemtypes
.itemtype
= localization
.code
156 AND localization
.entity
= 'itemtypes'
157 AND localization
.lang
= ?
160 my $sth = $dbh->prepare($query);
161 $sth->execute( $language );
163 if ( $style eq 'hash' ) {
165 while ( my $IT = $sth->fetchrow_hashref ) {
166 $itemtypes{ $IT->{'itemtype'} } = $IT;
168 return ( \
%itemtypes );
170 return [ sort { lc $a->{translated_description
} cmp lc $b->{translated_description
} } @
{ $sth->fetchall_arrayref( {} ) } ];
174 =head2 GetItemTypesCategorized
176 $categories = GetItemTypesCategorized();
178 Returns a hashref containing search categories.
179 A search category will be put in the hash if at least one of its itemtypes is visible in OPAC.
180 The categories must be part of Authorized Values (ITEMTYPECAT)
184 sub GetItemTypesCategorized
{
185 my $dbh = C4
::Context
->dbh;
186 # Order is important, so that partially hidden (some items are not visible in OPAC) search
187 # categories will be visible. hideinopac=0 must be last.
189 SELECT itemtype
, description
, imageurl
, hideinopac
, 0 as
'iscat' FROM itemtypes WHERE ISNULL
(searchcategory
) or length(searchcategory
) = 0
191 SELECT DISTINCT searchcategory AS
`itemtype`,
192 authorised_values
.lib_opac AS description
,
193 authorised_values
.imageurl AS imageurl
,
194 hideinopac
, 1 as
'iscat'
196 LEFT JOIN authorised_values ON searchcategory
= authorised_value
197 WHERE searchcategory
> '' and hideinopac
=1
199 SELECT DISTINCT searchcategory AS
`itemtype`,
200 authorised_values
.lib_opac AS description
,
201 authorised_values
.imageurl AS imageurl
,
202 hideinopac
, 1 as
'iscat'
204 LEFT JOIN authorised_values ON searchcategory
= authorised_value
205 WHERE searchcategory
> '' and hideinopac
=0
207 return ($dbh->selectall_hashref($query,'itemtype'));
210 =head2 GetItemTypesByCategory
212 @results = GetItemTypesByCategory( $searchcategory );
214 Returns the itemtype code of all itemtypes included in a searchcategory.
218 sub GetItemTypesByCategory
{
222 my $dbh = C4
::Context
->dbh;
223 my $query = qq|SELECT itemtype FROM itemtypes WHERE searchcategory
=?
|;
224 my $tmp=$dbh->selectcol_arrayref($query,undef,$category);
228 =head2 getitemtypeinfo
230 $itemtype = &getitemtypeinfo($itemtype, [$interface]);
232 Returns information about an itemtype. The optional $interface argument
233 sets which interface ('opac' or 'intranet') to return the imageurl for.
234 Defaults to intranet.
238 sub getitemtypeinfo
{
239 my ($itemtype, $interface) = @_;
240 my $dbh = C4
::Context
->dbh;
241 require C4
::Languages
;
242 my $language = C4
::Languages
::getlanguage
();
243 my $it = $dbh->selectrow_hashref(q
|
246 itemtypes
.description
,
247 itemtypes
.rentalcharge
,
248 itemtypes
.notforloan
,
251 itemtypes
.checkinmsg
,
252 itemtypes
.checkinmsgtype
,
253 itemtypes
.sip_media_type
,
254 COALESCE
( localization
.translation
, itemtypes
.description
) AS translated_description
256 LEFT JOIN localization ON itemtypes
.itemtype
= localization
.code
257 AND localization
.entity
= 'itemtypes'
258 AND localization
.lang
= ?
259 WHERE itemtypes
.itemtype
= ?
260 |, undef, $language, $itemtype );
262 $it->{imageurl
} = getitemtypeimagelocation
( ( ( defined $interface && $interface eq 'opac' ) ?
'opac' : 'intranet' ), $it->{imageurl
} );
267 =head2 getitemtypeimagedir
269 my $directory = getitemtypeimagedir( 'opac' );
271 pass in 'opac' or 'intranet'. Defaults to 'opac'.
273 returns the full path to the appropriate directory containing images.
277 sub getitemtypeimagedir
{
278 my $src = shift || 'opac';
279 if ($src eq 'intranet') {
280 return C4
::Context
->config('intrahtdocs') . '/' .C4
::Context
->preference('template') . '/img/itemtypeimg';
282 return C4
::Context
->config('opachtdocs') . '/' . C4
::Context
->preference('opacthemes') . '/itemtypeimg';
286 sub getitemtypeimagesrc
{
287 my $src = shift || 'opac';
288 if ($src eq 'intranet') {
289 return '/intranet-tmpl' . '/' . C4
::Context
->preference('template') . '/img/itemtypeimg';
291 return '/opac-tmpl' . '/' . C4
::Context
->preference('opacthemes') . '/itemtypeimg';
295 sub getitemtypeimagelocation
{
296 my ( $src, $image ) = @_;
298 return '' if ( !$image );
301 my $scheme = ( URI
::Split
::uri_split
( $image ) )[0];
303 return $image if ( $scheme );
305 return getitemtypeimagesrc
( $src ) . '/' . $image;
308 =head3 _getImagesFromDirectory
310 Find all of the image files in a directory in the filesystem
312 parameters: a directory name
314 returns: a list of images in that directory.
316 Notes: this does not traverse into subdirectories. See
317 _getSubdirectoryNames for help with that.
318 Images are assumed to be files with .gif or .png file extensions.
319 The image names returned do not have the directory name on them.
323 sub _getImagesFromDirectory
{
324 my $directoryname = shift;
325 return unless defined $directoryname;
326 return unless -d
$directoryname;
328 if ( opendir ( my $dh, $directoryname ) ) {
329 my @images = grep { /\.(gif|png)$/i } readdir( $dh );
331 @images = sort(@images);
334 warn "unable to opendir $directoryname: $!";
339 =head3 _getSubdirectoryNames
341 Find all of the directories in a directory in the filesystem
343 parameters: a directory name
345 returns: a list of subdirectories in that directory.
347 Notes: this does not traverse into subdirectories. Only the first
348 level of subdirectories are returned.
349 The directory names returned don't have the parent directory name on them.
353 sub _getSubdirectoryNames
{
354 my $directoryname = shift;
355 return unless defined $directoryname;
356 return unless -d
$directoryname;
358 if ( opendir ( my $dh, $directoryname ) ) {
359 my @directories = grep { -d File
::Spec
->catfile( $directoryname, $_ ) && ! ( /^\./ ) } readdir( $dh );
363 warn "unable to opendir $directoryname: $!";
370 returns: a listref of hashrefs. Each hash represents another collection of images.
372 { imagesetname => 'npl', # the name of the image set (npl is the original one)
373 images => listref of image hashrefs
376 each image is represented by a hashref like this:
378 { KohaImage => 'npl/image.gif',
379 StaffImageUrl => '/intranet-tmpl/prog/img/itemtypeimg/npl/image.gif',
380 OpacImageURL => '/opac-tmpl/prog/itemtypeimg/npl/image.gif'
381 checked => 0 or 1: was this the image passed to this method?
382 Note: I'd like to remove this somehow.
389 my $checked = $params{'checked'} || '';
391 my $paths = { staff
=> { filesystem
=> getitemtypeimagedir
('intranet'),
392 url
=> getitemtypeimagesrc
('intranet'),
394 opac
=> { filesystem
=> getitemtypeimagedir
('opac'),
395 url
=> getitemtypeimagesrc
('opac'),
399 my @imagesets = (); # list of hasrefs of image set data to pass to template
400 my @subdirectories = _getSubdirectoryNames
( $paths->{'staff'}{'filesystem'} );
401 foreach my $imagesubdir ( @subdirectories ) {
402 warn $imagesubdir if $DEBUG;
403 my @imagelist = (); # hashrefs of image info
404 my @imagenames = _getImagesFromDirectory
( File
::Spec
->catfile( $paths->{'staff'}{'filesystem'}, $imagesubdir ) );
405 my $imagesetactive = 0;
406 foreach my $thisimage ( @imagenames ) {
408 { KohaImage
=> "$imagesubdir/$thisimage",
409 StaffImageUrl
=> join( '/', $paths->{'staff'}{'url'}, $imagesubdir, $thisimage ),
410 OpacImageUrl
=> join( '/', $paths->{'opac'}{'url'}, $imagesubdir, $thisimage ),
411 checked
=> "$imagesubdir/$thisimage" eq $checked ?
1 : 0,
414 $imagesetactive = 1 if "$imagesubdir/$thisimage" eq $checked;
416 push @imagesets, { imagesetname
=> $imagesubdir,
417 imagesetactive
=> $imagesetactive,
418 images
=> \
@imagelist };
426 $printers = &GetPrinters();
427 @queues = keys %$printers;
429 Returns information about existing printer queues.
431 C<$printers> is a reference-to-hash whose keys are the print queues
432 defined in the printers table of the Koha database. The values are
433 references-to-hash, whose keys are the fields in the printers table.
439 my $dbh = C4
::Context
->dbh;
440 my $sth = $dbh->prepare("select * from printers");
442 while ( my $printer = $sth->fetchrow_hashref ) {
443 $printers{ $printer->{'printqueue'} } = $printer;
445 return ( \
%printers );
450 $printer = GetPrinter( $query, $printers );
455 my ( $query, $printers ) = @_; # get printer for this query from printers
456 my $printer = $query->param('printer');
457 my %cookie = $query->cookie('userenv');
458 ($printer) || ( $printer = $cookie{'printer'} ) || ( $printer = '' );
459 ( $printers->{$printer} ) || ( $printer = ( keys %$printers )[0] );
465 Returns the number of pages to display in a pagination bar, given the number
466 of items and the number of items per page.
471 my ( $nb_items, $nb_items_per_page ) = @_;
473 return int( ( $nb_items - 1 ) / $nb_items_per_page ) + 1;
478 (@themes) = &getallthemes('opac');
479 (@themes) = &getallthemes('intranet');
481 Returns an array of all available themes.
489 if ( $type eq 'intranet' ) {
490 $htdocs = C4
::Context
->config('intrahtdocs');
493 $htdocs = C4
::Context
->config('opachtdocs');
495 opendir D
, "$htdocs";
496 my @dirlist = readdir D
;
497 foreach my $directory (@dirlist) {
498 next if $directory eq 'lib';
499 -d
"$htdocs/$directory/en" and push @themes, $directory;
506 if ( C4
::Context
->preference("marcflavour") eq "UNIMARC" ) {
511 tags
=> [ qw
/ 600ab 601ab 602a 604at 605a 606ax 610a / ],
517 tags
=> [ qw
/ 607a / ],
523 tags
=> [ qw
/ 500a 501a 503a / ],
529 tags
=> [ qw
/ 700ab 701ab 702ab / ],
530 sep
=> C4
::Context
->preference("UNIMARCAuthorsFacetsSeparator"),
535 tags
=> [ qw
/ 225a / ],
541 tags
=> [ qw
/ 995e / ],
545 unless ( Koha
::Libraries
->search->count == 1 )
547 my $DisplayLibraryFacets = C4
::Context
->preference('DisplayLibraryFacets');
548 if ( $DisplayLibraryFacets eq 'both'
549 || $DisplayLibraryFacets eq 'holding' )
554 idx
=> 'holdingbranch',
555 label
=> 'HoldingLibrary',
556 tags
=> [qw
/ 995c /],
561 if ( $DisplayLibraryFacets eq 'both'
562 || $DisplayLibraryFacets eq 'home' )
568 label
=> 'HomeLibrary',
569 tags
=> [qw
/ 995b /],
580 tags
=> [ qw
/ 650a / ],
585 # label => 'People and Organizations',
586 # tags => [ qw/ 600a 610a 611a / ],
592 tags
=> [ qw
/ 651a / ],
598 tags
=> [ qw
/ 630a / ],
604 tags
=> [ qw
/ 100a 110a 700a / ],
610 tags
=> [ qw
/ 440a 490a / ],
615 label
=> 'ItemTypes',
616 tags
=> [ qw
/ 952y 942c / ],
622 tags
=> [ qw
/ 952c / ],
626 unless ( Koha
::Libraries
->search->count == 1 )
628 my $DisplayLibraryFacets = C4
::Context
->preference('DisplayLibraryFacets');
629 if ( $DisplayLibraryFacets eq 'both'
630 || $DisplayLibraryFacets eq 'holding' )
635 idx
=> 'holdingbranch',
636 label
=> 'HoldingLibrary',
637 tags
=> [qw
/ 952b /],
642 if ( $DisplayLibraryFacets eq 'both'
643 || $DisplayLibraryFacets eq 'home' )
649 label
=> 'HomeLibrary',
650 tags
=> [qw
/ 952a /],
661 Return a href where a key is associated to a href. You give a query,
662 the name of the key among the fields returned by the query. If you
663 also give as third argument the name of the value, the function
664 returns a href of scalar. The optional 4th argument is an arrayref of
665 items passed to the C<execute()> call. It is designed to bind
666 parameters to any placeholders in your SQL.
675 # generic href of any information on the item, href of href.
676 my $iteminfos_of = get_infos_of($query, 'itemnumber');
677 print $iteminfos_of->{$itemnumber}{barcode};
679 # specific information, href of scalar
680 my $barcode_of_item = get_infos_of($query, 'itemnumber', 'barcode');
681 print $barcode_of_item->{$itemnumber};
686 my ( $query, $key_name, $value_name, $bind_params ) = @_;
688 my $dbh = C4
::Context
->dbh;
690 my $sth = $dbh->prepare($query);
691 $sth->execute( @
$bind_params );
694 while ( my $row = $sth->fetchrow_hashref ) {
695 if ( defined $value_name ) {
696 $infos_of{ $row->{$key_name} } = $row->{$value_name};
699 $infos_of{ $row->{$key_name} } = $row;
707 =head2 get_notforloan_label_of
709 my $notforloan_label_of = get_notforloan_label_of();
711 Each authorised value of notforloan (information available in items and
712 itemtypes) is link to a single label.
714 Returns a href where keys are authorised values and values are corresponding
717 foreach my $authorised_value (keys %{$notforloan_label_of}) {
719 "authorised_value: %s => %s\n",
721 $notforloan_label_of->{$authorised_value}
727 # FIXME - why not use GetAuthorisedValues ??
729 sub get_notforloan_label_of
{
730 my $dbh = C4
::Context
->dbh;
733 SELECT authorised_value
734 FROM marc_subfield_structure
735 WHERE kohafield = \'items.notforloan\'
738 my $sth = $dbh->prepare($query);
740 my ($statuscode) = $sth->fetchrow_array();
745 FROM authorised_values
748 $sth = $dbh->prepare($query);
749 $sth->execute($statuscode);
750 my %notforloan_label_of;
751 while ( my $row = $sth->fetchrow_hashref ) {
752 $notforloan_label_of{ $row->{authorised_value
} } = $row->{lib
};
756 return \
%notforloan_label_of;
759 =head2 GetAuthorisedValues
761 $authvalues = GetAuthorisedValues([$category]);
763 This function returns all authorised values from the'authorised_value' table in a reference to array of hashrefs.
765 C<$category> returns authorised values for just one category (optional).
767 C<$opac> If set to a true value, displays OPAC descriptions rather than normal ones when they exist.
771 sub GetAuthorisedValues
{
772 my ( $category, $opac ) = @_;
774 # Is this cached already?
775 $opac = $opac ?
1 : 0; # normalise to be safe
777 C4
::Context
->userenv ? C4
::Context
->userenv->{"branch"} : "";
779 "AuthorisedValues-$category-$opac-$branch_limit";
780 my $cache = Koha
::Caches
->get_instance();
781 my $result = $cache->get_from_cache($cache_key);
782 return $result if $result;
785 my $dbh = C4
::Context
->dbh;
788 FROM authorised_values av
791 LEFT JOIN authorised_values_branches ON
( id
= av_id
)
796 push @where_strings, "category = ?";
797 push @where_args, $category;
800 push @where_strings, "( branchcode = ? OR branchcode IS NULL )";
801 push @where_args, $branch_limit;
803 if(@where_strings > 0) {
804 $query .= " WHERE " . join(" AND ", @where_strings);
806 $query .= ' ORDER BY category, ' . (
807 $opac ?
'COALESCE(lib_opac, lib)'
811 my $sth = $dbh->prepare($query);
813 $sth->execute( @where_args );
814 while (my $data=$sth->fetchrow_hashref) {
815 if ($opac && $data->{lib_opac
}) {
816 $data->{lib
} = $data->{lib_opac
};
818 push @results, $data;
822 $cache->set_in_cache( $cache_key, \
@results, { expiry
=> 5 } );
828 my $escaped_string = C4::Koha::xml_escape($string);
830 Convert &, <, >, ', and " in a string to XML entities
836 return '' unless defined $str;
840 $str =~ s/'/'/g;
841 $str =~ s/"/"/g;
845 =head2 display_marc_indicators
847 my $display_form = C4::Koha::display_marc_indicators($field);
849 C<$field> is a MARC::Field object
851 Generate a display form of the indicators of a variable
852 MARC field, replacing any blanks with '#'.
856 sub display_marc_indicators
{
859 if ($field && $field->tag() >= 10) {
860 $indicators = $field->indicator(1) . $field->indicator(2);
861 $indicators =~ s/ /#/g;
866 sub GetNormalizedUPC
{
867 my ($marcrecord,$marcflavour) = @_;
869 return unless $marcrecord;
870 if ($marcflavour eq 'UNIMARC') {
871 my @fields = $marcrecord->field('072');
872 foreach my $field (@fields) {
873 my $upc = _normalize_match_point
($field->subfield('a'));
880 else { # assume marc21 if not unimarc
881 my @fields = $marcrecord->field('024');
882 foreach my $field (@fields) {
883 my $indicator = $field->indicator(1);
884 my $upc = _normalize_match_point
($field->subfield('a'));
885 if ($upc && $indicator == 1 ) {
892 # Normalizes and returns the first valid ISBN found in the record
893 # ISBN13 are converted into ISBN10. This is required to get some book cover images.
894 sub GetNormalizedISBN
{
895 my ($isbn,$marcrecord,$marcflavour) = @_;
897 # Koha attempts to store multiple ISBNs in biblioitems.isbn, separated by " | "
898 # anything after " | " should be removed, along with the delimiter
899 ($isbn) = split(/\|/, $isbn );
900 return _isbn_cleanup
($isbn);
903 return unless $marcrecord;
905 if ($marcflavour eq 'UNIMARC') {
906 my @fields = $marcrecord->field('010');
907 foreach my $field (@fields) {
908 my $isbn = $field->subfield('a');
910 return _isbn_cleanup
($isbn);
914 else { # assume marc21 if not unimarc
915 my @fields = $marcrecord->field('020');
916 foreach my $field (@fields) {
917 $isbn = $field->subfield('a');
919 return _isbn_cleanup
($isbn);
925 sub GetNormalizedEAN
{
926 my ($marcrecord,$marcflavour) = @_;
928 return unless $marcrecord;
930 if ($marcflavour eq 'UNIMARC') {
931 my @fields = $marcrecord->field('073');
932 foreach my $field (@fields) {
933 my $ean = _normalize_match_point
($field->subfield('a'));
939 else { # assume marc21 if not unimarc
940 my @fields = $marcrecord->field('024');
941 foreach my $field (@fields) {
942 my $indicator = $field->indicator(1);
943 my $ean = _normalize_match_point
($field->subfield('a'));
944 if ( $ean && $indicator == 3 ) {
951 sub GetNormalizedOCLCNumber
{
952 my ($marcrecord,$marcflavour) = @_;
953 return unless $marcrecord;
955 if ($marcflavour ne 'UNIMARC' ) {
956 my @fields = $marcrecord->field('035');
957 foreach my $field (@fields) {
958 my $oclc = $field->subfield('a');
959 if ($oclc =~ /OCoLC/) {
960 $oclc =~ s/\(OCoLC\)//;
970 sub GetAuthvalueDropbox
{
971 my ( $authcat, $default ) = @_;
972 my $branch_limit = C4
::Context
->userenv ? C4
::Context
->userenv->{"branch"} : "";
973 my $dbh = C4
::Context
->dbh;
977 FROM authorised_values
980 LEFT JOIN authorised_values_branches ON
( id
= av_id
)
985 $query .= " AND ( branchcode = ? OR branchcode IS NULL )" if $branch_limit;
986 $query .= " GROUP BY lib ORDER BY category, lib, lib_opac";
987 my $sth = $dbh->prepare($query);
988 $sth->execute( $authcat, $branch_limit ?
$branch_limit : () );
991 my $option_list = [];
992 my @authorised_values = ( q{} );
993 while (my $av = $sth->fetchrow_hashref) {
994 push @
{$option_list}, {
995 value
=> $av->{authorised_value
},
997 default => ($default eq $av->{authorised_value
}),
1001 if ( @
{$option_list} ) {
1002 return $option_list;
1008 =head2 GetDailyQuote($opts)
1010 Takes a hashref of options
1012 Currently supported options are:
1014 'id' An exact quote id
1015 'random' Select a random quote
1016 noop When no option is passed in, this sub will return the quote timestamped for the current day
1018 The function returns an anonymous hash following this format:
1021 'source' => 'source-of-quote',
1022 'timestamp' => 'timestamp-value',
1023 'text' => 'text-of-quote',
1029 # This is definitely a candidate for some sort of caching once we finally settle caching/persistence issues...
1030 # at least for default option
1034 my $dbh = C4
::Context
->dbh;
1039 $query = 'SELECT * FROM quotes WHERE id = ?';
1040 $sth = $dbh->prepare($query);
1041 $sth->execute($opts{'id'});
1042 $quote = $sth->fetchrow_hashref();
1044 elsif ($opts{'random'}) {
1045 # Fall through... we also return a random quote as a catch-all if all else fails
1048 $query = 'SELECT * FROM quotes WHERE timestamp LIKE CONCAT(CURRENT_DATE,\'%\') ORDER BY timestamp DESC LIMIT 0,1';
1049 $sth = $dbh->prepare($query);
1051 $quote = $sth->fetchrow_hashref();
1053 unless ($quote) { # if there are not matches, choose a random quote
1054 # get a list of all available quote ids
1055 $sth = C4
::Context
->dbh->prepare('SELECT count(*) FROM quotes;');
1057 my $range = ($sth->fetchrow_array)[0];
1058 # chose a random id within that range if there is more than one quote
1059 my $offset = int(rand($range));
1061 $query = 'SELECT * FROM quotes ORDER BY id LIMIT 1 OFFSET ?';
1062 $sth = C4
::Context
->dbh->prepare($query);
1063 # see http://www.perlmonks.org/?node_id=837422 for why
1064 # we're being verbose and using bind_param
1065 $sth->bind_param(1, $offset, SQL_INTEGER
);
1067 $quote = $sth->fetchrow_hashref();
1068 # update the timestamp for that quote
1069 $query = 'UPDATE quotes SET timestamp = ? WHERE id = ?';
1070 $sth = C4
::Context
->dbh->prepare($query);
1072 DateTime
::Format
::MySQL
->format_datetime( dt_from_string
() ),
1079 sub _normalize_match_point
{
1080 my $match_point = shift;
1081 (my $normalized_match_point) = $match_point =~ /([\d-]*[X]*)/;
1082 $normalized_match_point =~ s/-//g;
1084 return $normalized_match_point;
1089 return NormalizeISBN
(
1092 format
=> 'ISBN-10',
1098 =head2 NormalizedISBN
1100 my $isbns = NormalizedISBN({
1102 strip_hyphens => [0,1],
1103 format => ['ISBN-10', 'ISBN-13']
1106 Returns an isbn validated by Business::ISBN.
1107 Optionally strips hyphens and/or forces the isbn
1108 to be of the specified format.
1110 If the string cannot be validated as an isbn,
1118 my $string = $params->{isbn
};
1119 my $strip_hyphens = $params->{strip_hyphens
};
1120 my $format = $params->{format
};
1122 return unless $string;
1124 my $isbn = Business
::ISBN
->new($string);
1126 if ( $isbn && $isbn->is_valid() ) {
1128 if ( $format eq 'ISBN-10' ) {
1129 $isbn = $isbn->as_isbn10();
1131 elsif ( $format eq 'ISBN-13' ) {
1132 $isbn = $isbn->as_isbn13();
1134 return unless $isbn;
1136 if ($strip_hyphens) {
1137 $string = $isbn->as_string( [] );
1139 $string = $isbn->as_string();
1146 =head2 GetVariationsOfISBN
1148 my @isbns = GetVariationsOfISBN( $isbn );
1150 Returns a list of variations of the given isbn in
1151 both ISBN-10 and ISBN-13 formats, with and without
1154 In a scalar context, the isbns are returned as a
1155 string delimited by ' | '.
1159 sub GetVariationsOfISBN
{
1162 return unless $isbn;
1166 push( @isbns, NormalizeISBN
({ isbn
=> $isbn }) );
1167 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-10' }) );
1168 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-13' }) );
1169 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-10', strip_hyphens
=> 1 }) );
1170 push( @isbns, NormalizeISBN
({ isbn
=> $isbn, format
=> 'ISBN-13', strip_hyphens
=> 1 }) );
1172 # Strip out any "empty" strings from the array
1173 @isbns = grep { defined($_) && $_ =~ /\S/ } @isbns;
1175 return wantarray ?
@isbns : join( " | ", @isbns );
1178 =head2 GetVariationsOfISBNs
1180 my @isbns = GetVariationsOfISBNs( @isbns );
1182 Returns a list of variations of the given isbns in
1183 both ISBN-10 and ISBN-13 formats, with and without
1186 In a scalar context, the isbns are returned as a
1187 string delimited by ' | '.
1191 sub GetVariationsOfISBNs
{
1194 @isbns = map { GetVariationsOfISBN
( $_ ) } @isbns;
1196 return wantarray ?
@isbns : join( " | ", @isbns );
1199 =head2 NormalizedISSN
1201 my $issns = NormalizedISSN({
1203 strip_hyphen => [0,1]
1206 Returns an issn validated by Business::ISSN.
1207 Optionally strips hyphen.
1209 If the string cannot be validated as an issn,
1217 my $string = $params->{issn
};
1218 my $strip_hyphen = $params->{strip_hyphen
};
1220 my $issn = Business
::ISSN
->new($string);
1222 if ( $issn && $issn->is_valid ){
1224 if ($strip_hyphen) {
1225 $string = $issn->_issn;
1228 $string = $issn->as_string;
1235 =head2 GetVariationsOfISSN
1237 my @issns = GetVariationsOfISSN( $issn );
1239 Returns a list of variations of the given issn in
1240 with and without a hyphen.
1242 In a scalar context, the issns are returned as a
1243 string delimited by ' | '.
1247 sub GetVariationsOfISSN
{
1250 return unless $issn;
1253 my $str = NormalizeISSN
({ issn
=> $issn });
1256 push @issns, NormalizeISSN
({ issn
=> $issn, strip_hyphen
=> 1 });
1261 # Strip out any "empty" strings from the array
1262 @issns = grep { defined($_) && $_ =~ /\S/ } @issns;
1264 return wantarray ?
@issns : join( " | ", @issns );
1267 =head2 GetVariationsOfISSNs
1269 my @issns = GetVariationsOfISSNs( @issns );
1271 Returns a list of variations of the given issns in
1272 with and without a hyphen.
1274 In a scalar context, the issns are returned as a
1275 string delimited by ' | '.
1279 sub GetVariationsOfISSNs
{
1282 @issns = map { GetVariationsOfISSN
( $_ ) } @issns;
1284 return wantarray ?
@issns : join( " | ", @issns );
1288 =head2 IsKohaFieldLinked
1290 my $is_linked = IsKohaFieldLinked({
1291 kohafield => $kohafield,
1292 frameworkcode => $frameworkcode,
1295 Return 1 if the field is linked
1299 sub IsKohaFieldLinked
{
1300 my ( $params ) = @_;
1301 my $kohafield = $params->{kohafield
};
1302 my $frameworkcode = $params->{frameworkcode
} || '';
1303 my $dbh = C4
::Context
->dbh;
1304 my $is_linked = $dbh->selectcol_arrayref( q
|
1306 FROM marc_subfield_structure
1307 WHERE frameworkcode
= ?
1309 |,{}, $frameworkcode, $kohafield );
1310 return $is_linked->[0];