foreach my $orderinfokey (grep(!/ordernumber/, keys %$orderinfo)){
# ... and skip hash entries that are not in the aqorders table
# FIXME : probably not the best way to do it (would be better to have a correct hash)
- next unless grep(/^$orderinfokey$/, @$colnames);
+ next unless grep { $_ eq $orderinfokey } @$colnames;
$query .= "$orderinfokey=?, ";
push(@params, $orderinfo->{$orderinfokey});
}
if($args{order_by}) {
my ($column, $direction) = split / /, $args{order_by};
- if(grep /^$column$/, @columns) {
+ if(grep { $_ eq $column } @columns) {
$direction ||= 'ASC';
$query .= " ORDER BY $column $direction";
}
my @set_strs;
my @set_args;
foreach my $key (keys %invoice) {
- if(0 < grep(/^$key$/, @columns)) {
+ if(0 < grep { $_ eq $key } @columns) {
push @set_strs, "$key = ?";
push @set_args, ($invoice{$key} || undef);
}
my @set_strs;
my @set_args;
foreach my $key (keys %invoice) {
- if(0 < grep(/^$key$/, @columns)) {
+ if(0 < grep { $_ eq $key } @columns) {
push @set_strs, "$key = ?";
push @set_args, ($invoice{$key} || undef);
}
my $dbh = C4::Context->dbh;
my $order_by = $parameters->{order_by} || 'import_record_id';
- ( $order_by ) = grep( /^$order_by$/, qw( import_record_id title status overlay_status ) ) ? $order_by : 'import_record_id';
+ ( $order_by ) = grep( { $_ eq $order_by } qw( import_record_id title status overlay_status ) ) ? $order_by : 'import_record_id';
my $order_by_direction =
uc( $parameters->{order_by_direction} // 'ASC' ) eq 'DESC' ? 'DESC' : 'ASC';
push @columns, Koha::Database->new()->schema()->resultset('Biblioitem')->result_source->columns;
my @operators = qw(= != > < >= <= like);
my $field = $filter->{field} // q{};
- if ( (0 < grep /^$field$/, @columns) or (substr($field, 0, 5) eq 'marc:') ) {
+ if ( (0 < grep { $_ eq $field } @columns) or (substr($field, 0, 5) eq 'marc:') ) {
my $op = $filter->{operator};
my $query = $filter->{query};
- if (!$op or (0 == grep /^$op$/, @operators)) {
+ if (!$op or (0 == grep { $_ eq $op } @operators)) {
$op = '='; # default operator
}
|;
for my $condition ( @$conditions ) {
if (
- grep {/^$condition->{field}$/} @item_columns
- or grep {/^$condition->{field}$/} @biblioitem_columns
+ grep { $_ eq $condition->{field} } @item_columns
+ or grep { $_ eq $condition->{field} } @biblioitem_columns
) {
if ( $condition->{value} =~ /\|/ ) {
my @values = split /\|/, $condition->{value};
my @columns = $schema->source('Item')->columns;
foreach my $fn ( @spfields ) {
- push ( @ret, $fn ) if ( grep(/^$fn$/, @columns) );
+ push ( @ret, $fn ) if ( grep { $_ eq $fn } @columns );
}
$ret = join( '|', @ret);
}
}
if ($operator eq 'notequal') {
- if(0 == grep /^$value$/, @all_subfield_values) {
+ if(0 == grep { $_ eq $value } @all_subfield_values) {
return 1;
}
}
else {
- if(0 < grep /^$value$/, @all_subfield_values) {
+ if(0 < grep { $_ eq $value } @all_subfield_values) {
return 1;
}
}
# Put 'print' in first if exists
# It avoid to sent a print notice with an email or sms template is no email or sms is defined
@mtts = uniq( 'print', @mtts )
- if grep {/^print$/} @mtts;
+ if grep { $_ eq 'print' } @mtts;
return \@mtts;
}
my $data = $field->as_string( $subfield_letters, $facet->{ sep } );
- unless ( grep { /^\Q$data\E$/ } @used_datas ) {
+ unless ( grep { $_ eq $data } @used_datas ) {
push @used_datas, $data;
$facets_counter->{ $facet->{ idx } }->{ $data }++;
}
# this happens when selecting a subject on the opac-detail page
@limits = grep {!/^$/} @limits;
my $original_q = $q; # without available part
- unless ( grep { /^available$/ } @limits ) {
+ unless ( grep { $_ eq 'available' } @limits ) {
$q =~ s| and \( \(allrecords,AlwaysMatches=''\) and \(not-onloan-count,st-numeric >= 1\) and \(lost,st-numeric=0\) \)||;
$original_q = $q;
}
if ( @limits ) {
- if ( grep { /^available$/ } @limits ) {
+ if ( grep { $_ eq 'available' } @limits ) {
$q .= q| and ( (allrecords,AlwaysMatches='') and (not-onloan-count,st-numeric >= 1) and (lost,st-numeric=0) )|;
delete $limits['available'];
}
### Would use substr and index But be careful to previous presence of ()
$recievedlist .= "; $serialseq" unless ( index( $recievedlist, $serialseq ) > 0 );
}
- if ( grep { /^$status$/ } (MISSING_STATUSES) ) {
+ if ( grep { $_ eq $status } (MISSING_STATUSES) ) {
$missinglist .= "; $serialseq" unless ( index( $missinglist, $serialseq ) > 0 );
}
}
my @invalid_params = ();
for my $myparam (keys %$params ) {
- push @invalid_params, $myparam unless grep (/^$myparam$/, @allowed_keys);
+ push @invalid_params, $myparam unless grep { $_ eq $myparam } @allowed_keys;
}
if (scalar @invalid_params > 0 ) {
croak ("UpdateStats received invalid param(s): ".join (", ",@invalid_params ));
carp "Empty argument key to get_tag_rows: ignoring!";
next;
}
- unless (1 == scalar grep {/^ $key $/x} @ok_fields) {
+ unless (1 == scalar grep { $_ eq $key } @ok_fields) {
carp "get_tag_rows received unreconized argument key '$key'.";
next;
}
carp "Empty argument key to get_tags: ignoring!";
next;
}
- unless (1 == scalar grep {/^ $key $/x} @ok_fields) {
+ unless (1 == scalar grep { $_ eq $key } @ok_fields) {
carp "get_tags received unreconized argument key '$key'.";
next;
}
carp "Empty argument key to get_approval_rows: ignoring!";
next;
}
- unless (1 == scalar grep {/^ $key $/x} @ok_fields) {
+ unless (1 == scalar grep { $_ eq $key } @ok_fields) {
carp "get_approval_rows received unreconized argument key '$key'.";
next;
}
# Do that after iTotalQuery!
if ( defined $branchcode and $branchcode ) {
@restricted_branchcodes = @restricted_branchcodes
- ? grep { /^$branchcode$/ } @restricted_branchcodes
+ ? grep { $_ eq $branchcode } @restricted_branchcodes
? ($branchcode)
: (undef) # Do not return any results
: ($branchcode);
my @columns = @{$self->_columns()};
foreach my $p ( keys %$properties ) {
- unless ( grep {/^$p$/} @columns ) {
+ unless ( grep { $_ eq $p } @columns ) {
Koha::Exceptions::Object::PropertyNotFound->throw( "No property $p for " . ref($self) );
}
}
my @columns = @{$self->_columns()};
# Using direct setter/getter like $item->barcode() or $item->barcode($barcode);
- if ( grep {/^$method$/} @columns ) {
+ if ( grep { $_ eq $method } @columns ) {
if ( @_ ) {
$self->_result()->set_column( $method, @_ );
return $self;
Koha::Exceptions::Object::MethodNotCoveredByTests->throw(
error => sprintf("The method %s->%s is not covered by tests!", ref($self), $method),
show_trace => 1
- ) unless grep { /^$method$/ } @known_methods;
+ ) unless grep { $_ eq $method } @known_methods;
my $r = eval { $self->_result->$method(@_) };
$method =~ s/.*:://;
- unless ( grep { /^$method$/ } @known_methods ) {
+ unless ( grep { $_ eq $method } @known_methods ) {
my $class = ref($self) ? ref($self) : $self;
Koha::Exceptions::Object::MethodNotCoveredByTests->throw(
error => sprintf("The method %s->%s is not covered by tests!", $class, $method),
if ( $op eq 'select' ) {
@result_order_loop = map {
my $order = $_;
- ( grep { /^$order->{ordernumber}$/ } @ordernumbers ) ? () : $order
+ ( grep {$_ eq $order->{ordernumber}} @ordernumbers ) ? () : $order
} @{ C4::Acquisition::GetHistory(%$filters) };
@selected_order_loop =
for my $field (
qw(currency budget_id order_internalnote order_vendornote sort1 sort2 ))
{
- next if grep { /^$field$/ } @fields_to_copy;
+ next if grep { $_ eq $field } @fields_to_copy;
$default_values->{$field} = $input->param("all_$field");
}
{
text => $options{multiple}->{$option_value},
value => $option_value,
- selected => (grep /^$option_value$/, @values) ? 1 : 0,
+ selected => (grep { $_ eq $option_value } @values) ? 1 : 0,
}
}
keys %{ $options{multiple} }
my $search_field_name = $search_field_name[$i];
my $mapping_marc_field = $mapping_marc_field[$i];
my $mapping_facet = $mapping_facet[$i];
- $mapping_facet = ( grep {/^$search_field_name$/} @facetable_field_names ) ? $mapping_facet : 0;
+ $mapping_facet = ( grep { $_ eq $search_field_name } @facetable_field_names ) ? $mapping_facet : 0;
my $mapping_suggestible = $mapping_suggestible[$i];
my $mapping_sort = $mapping_sort[$i] eq 'undef' ? undef : $mapping_sort[$i];
my $mapping_search = $mapping_search[$i];
suggestible => $s->get_column('suggestible'),
search => $s->get_column('search'),
facet => $s->get_column('facet'),
- is_facetable => ( grep {/^$name$/} @facetable_field_names ) ? 1 : 0,
+ is_facetable => ( grep { $_ eq $name } @facetable_field_names ) ? 1 : 0,
};
}
my $basket = $myorder->{'basketno'};
if ((defined $myorder->{'datecancellationprinted'}) and ($myorder->{'datecancellationprinted'} ne '0000-00-00') ){
push @deletedorders_using_biblio, $myorder;
- unless (grep(/^$basket$/, @baskets_deletedorders)){
+ unless (grep{ $_ eq $basket } @baskets_deletedorders){
push @baskets_deletedorders,$myorder->{'basketno'};
}
}
else {
push @orders_using_biblio, $myorder;
- unless (grep(/^$basket$/, @baskets_orders)){
+ unless (grep{ $_ eq $basket } @baskets_orders){
push @baskets_orders,$myorder->{'basketno'};
}
}
my $basket = $myorder->{'basketno'};
if ((defined $myorder->{'datecancellationprinted'}) and ($myorder->{'datecancellationprinted'} ne '0000-00-00') ){
push @deletedorders_using_biblio, $myorder;
- unless (grep(/^$basket$/, @baskets_deletedorders)){
+ unless (grep{ $_ eq $basket } @baskets_deletedorders){
push @baskets_deletedorders,$myorder->{'basketno'};
}
}
else {
push @orders_using_biblio, $myorder;
- unless (grep(/^$basket$/, @baskets_orders)){
+ unless (grep { $_ eq $basket } @baskets_orders){
push @baskets_orders,$myorder->{'basketno'};
}
}
my $basket = $myorder->{'basketno'};
if ((defined $myorder->{'datecancellationprinted'}) and ($myorder->{'datecancellationprinted'} ne '0000-00-00') ){
push @deletedorders_using_biblio, $myorder;
- unless (grep(/^$basket$/, @baskets_deletedorders)){
+ unless (grep{ $_ eq $basket } @baskets_deletedorders){
push @baskets_deletedorders,$myorder->{'basketno'};
}
}
else {
push @orders_using_biblio, $myorder;
- unless (grep(/^$basket$/, @baskets_orders)){
+ unless (grep{ $_ eq $basket } @baskets_orders){
push @baskets_orders,$myorder->{'basketno'};
}
}
my $basket = $myorder->{'basketno'};
if ((defined $myorder->{'datecancellationprinted'}) and ($myorder->{'datecancellationprinted'} ne '0000-00-00') ){
push @deletedorders_using_biblio, $myorder;
- unless (grep(/^$basket$/, @baskets_deletedorders)){
+ unless (grep{ $_ eq $basket } @baskets_deletedorders){
push @baskets_deletedorders,$myorder->{'basketno'};
}
}
else {
push @orders_using_biblio, $myorder;
- unless (grep(/^$basket$/, @baskets_orders)){
+ unless (grep{ $_ eq $basket } @baskets_orders){
push @baskets_orders,$myorder->{'basketno'};
}
}
push @f, $columns[$i];
push @c, 'and';
- if ( grep /^$columns[$i]$/, qw( ccode homebranch holdingbranch location itype notforloan itemlost ) ) {
+ if ( grep { $_ eq $columns[$i] } qw( ccode homebranch holdingbranch location itype notforloan itemlost ) ) {
push @q, "$word";
push @op, '=';
} else {
my $basket = $myorder->{'basketno'};
if ((defined $myorder->{'datecancellationprinted'}) and ($myorder->{'datecancellationprinted'} ne '0000-00-00') ){
push @deletedorders_using_biblio, $myorder;
- unless (grep(/^$basket$/, @baskets_deletedorders)){
+ unless (grep { $_ eq $basket } @baskets_deletedorders){
push @baskets_deletedorders,$myorder->{'basketno'};
}
}
else {
push @orders_using_biblio, $myorder;
- unless (grep(/^$basket$/, @baskets_orders)){
+ unless (grep{ $_ eq $basket } @baskets_orders){
push @baskets_orders,$myorder->{'basketno'};
}
}
my $basket = $myorder->{'basketno'};
if ((defined $myorder->{'datecancellationprinted'}) and ($myorder->{'datecancellationprinted'} ne '0000-00-00') ){
push @deletedorders_using_biblio, $myorder;
- unless (grep(/^$basket$/, @baskets_deletedorders)){
+ unless (grep{ $_ eq $basket } @baskets_deletedorders){
push @baskets_deletedorders,$myorder->{'basketno'};
}
}
else {
push @orders_using_biblio, $myorder;
- unless (grep(/^$basket$/, @baskets_orders)){
+ unless (grep { $_ eq $basket } @baskets_orders){
push @baskets_orders,$myorder->{'basketno'};
}
}
$template_name = q|circ/circulation_batch_checkouts.tt|;
my @batch_category_codes = split '\|', C4::Context->preference('BatchCheckoutsValidCategories');
my $categorycode = $patron->categorycode;
- if ( $categorycode && grep {/^$categorycode$/} @batch_category_codes ) {
+ if ( $categorycode && grep { $_ eq $categorycode } @batch_category_codes ) {
$batch_allowed = 1;
} else {
$barcodes = [];
? Koha::Club::Template::Fields->find($field_id)
: Koha::Club::Template::Field->new();
- if ( grep( /^$field_id$/, @field_delete ) ) {
+ if ( grep { $_ eq $field_id } @field_delete ) {
$field->delete();
}
else {
? Koha::Club::Template::EnrollmentFields->find($field_id)
: Koha::Club::Template::EnrollmentField->new();
- if ( grep( /^$field_id$/, @field_delete ) ) {
+ if ( grep { $_ eq $field_id } @field_delete ) {
$field->delete();
}
else {
@all_messages = map {
my $letter_code = $_->{letter_code};
(
- grep { /^$letter_code$/ } @letter_codes
+ grep { $_ eq $letter_code } @letter_codes
) ? $_ : ()
} @all_messages if @letter_codes;
exit unless @all_messages;
$skip_borrower_category = [ map { uc $_} @$skip_borrower_category ];
my %category_to_process;
for my $cat ( @$borrower_category ) {
- unless ( grep { /^$cat$/ } @available_categories ) {
+ unless ( grep { $_ eq $cat } @available_categories ) {
pod2usage(
'-exitval' => 1,
'-message' => "The category $cat does not exist in the database",
}
if ( @$skip_borrower_category ) {
for my $cat ( @$skip_borrower_category ) {
- unless ( grep { /^$cat$/ } @available_categories ) {
+ unless ( grep { $_ eq $cat } @available_categories ) {
pod2usage(
'-exitval' => 1,
'-message' => "The category $cat does not exist in the database",
$skip_itemtype = [ map { uc $_} @$skip_itemtype ];
my %itemtype_to_process;
for my $it ( @$itemtype ) {
- unless ( grep { /^$it$/ } @available_itemtypes ) {
+ unless ( grep { $_ eq $it } @available_itemtypes ) {
pod2usage(
'-exitval' => 1,
'-message' => "The itemtype $it does not exist in the database",
}
if ( @$skip_itemtype ) {
for my $it ( @$skip_itemtype ) {
- unless ( grep { /^$it$/ } @available_itemtypes ) {
+ unless ( grep { $_ eq $it } @available_itemtypes ) {
pod2usage(
'-exitval' => 1,
'-message' => "The itemtype $it does not exist in the database",
}
our @tables_allowed_for_select = ( 'biblioitems', 'items', 'biblio', 'biblio_metadata' );
-unless ( grep { /^$table$/ } @tables_allowed_for_select ) {
+unless ( grep { $_ eq $table } @tables_allowed_for_select ) {
die "Cannot specify -t|--table with value '$table'. Only "
. ( join ', ', @tables_allowed_for_select )
. " are allowed.";
sub select_all_biblios {
$table = 'biblioitems'
- unless grep { /^$table$/ } @tables_allowed_for_select;
+ unless grep { $_ eq $table } @tables_allowed_for_select;
my $strsth = qq{ SELECT DISTINCT biblionumber FROM $table };
$strsth.=qq{ WHERE $where } if ($where);
$strsth.=qq{ LIMIT $length } if ($length && !$offset);
next if $entry =~ /^\./;
my $relentry = File::Spec->catfile($dir, $entry);
my $abspath = File::Spec->catfile($basedir, $relentry);
- if (-d $abspath and not grep /^$relentry$/, @blacklist) {
+ if (-d $abspath and not grep { $_ eq $relentry } @blacklist) {
push @directories_to_scan, $relentry;
} elsif (-f $abspath and $relentry =~ /\.(pl|pm)$/) {
push @files_to_scan, $relentry;
$cmd = lc $cmd;
if ( $cmd =~ /create|install|update/ ) {
my $installer = LangInstaller->new( $lang, $pref, $verbose );
- if ( $cmd ne 'create' and $lang and not grep( /^$lang$/, @{ $installer->{langs} } ) ) {
+ if ( $cmd ne 'create' and $lang and not grep( {$_ eq $lang} @{ $installer->{langs} } ) ) {
print "Unsupported language: $lang\n";
exit;
}
if ( C4::Context->preference('OPACAcquisitionDetails') ) {
$itm->{on_order} = 1
- if grep /^$itm->{itemnumber}$/, @itemnumbers_on_order;
+ if grep { $_ eq $itm->{itemnumber} } @itemnumbers_on_order;
}
my $itembranch = $itm->{$separatebranch};
my @libraries = Koha::Libraries->search;
if ( my @libraries_to_display = split '\|', C4::Context->preference('PatronSelfRegistrationLibraryList') ) {
- @libraries = map { my $b = $_; my $branchcode = $_->branchcode; grep( /^$branchcode$/, @libraries_to_display ) ? $b : () } @libraries;
+ @libraries = map { my $b = $_; my $branchcode = $_->branchcode; grep { $_ eq $branchcode } @libraries_to_display ? $b : () } @libraries;
}
my ( $min, $max ) = C4::Members::get_cardnumber_length();
if ( defined $min ) {
my @patron_categories = split '\|', C4::Context->preference('OPACHoldsIfAvailableAtPickupExceptions');
if ( @patron_categories ) {
my $categorycode = $patron->categorycode;
- $can_place_hold_if_available_at_pickup = grep /^$categorycode$/, @patron_categories;
+ $can_place_hold_if_available_at_pickup = grep { $_ eq $categorycode } @patron_categories;
}
}
@searches = map { $_->{type} ne $type ? $_ : () } @searches;
}
if ( @id ) {
- @searches = map { my $search = $_; ( grep {/^$search->{id}$/} @id ) ? () : $_ } @searches;
+ @searches = map { my $search = $_; ( grep { $_ eq $search->{id} } @id ) ? () : $_ } @searches;
}
}
C4::Search::History::set_to_session({ cgi => $cgi, search_history => \@searches });
@sort_by = $cgi->multi_param('sort_by');
$sort_by[0] = $default_sort_by if !$sort_by[0] && defined($default_sort_by);
foreach my $sort (@sort_by) {
- if ( grep { /^$sort$/ } @allowed_sortby ) {
+ if ( grep { $_ eq $sort } @allowed_sortby ) {
$template->param($sort => 1);
}
}
if ( $shelf ) {
$op = $referer;
my $sortfield = $query->param('sortfield');
- $sortfield = 'title' unless grep {/^$sortfield$/}qw( title author copyrightdate itemcallnumber dateadded );
+ $sortfield = 'title' unless grep { $_ eq $sortfield } qw( title author copyrightdate itemcallnumber dateadded );
if ( $shelf->can_be_managed( $loggedinuser ) ) {
$shelf->shelfname( scalar $query->param('shelfname') );
$shelf->sortfield( $sortfield );
my $attribute_type = $1;
return unless (grep {$attribute_type eq $_->{code}} @attribute_types);
} else {
- return unless (grep /^$line$/, @valid_names);
+ return unless (grep { $_ eq $line } @valid_names);
}
if ($column =~ /^patron_attr\.(.*)/) {
my $attribute_type = $1;
return unless (grep {$attribute_type eq $_->{code}} @attribute_types);
} else {
- return unless (grep /^$column$/, @valid_names);
+ return unless (grep { $_ eq $column } @valid_names);
}
return if ($digits and $digits !~ /^\d+$/);
- return if ($status and (grep /^$status$/, qw(debarred gonenoaddress lost)) == 0);
- return if ($activity and (grep /^$activity$/, qw(active nonactive)) == 0);
+ return if ($status and (grep { $_ eq $status } qw(debarred gonenoaddress lost)) == 0);
+ return if ($activity and (grep { $_ eq $activity } qw(active nonactive)) == 0);
# Filters
my $linefilter;
if ( $filename ) {
my $mimetype = $query->uploadInfo($filename)->{'Content-Type'};
my @valid_mimetypes = qw( application/octet-stream text/csv text/plain application/vnd.ms-excel );
- unless ( grep { /^$mimetype$/ } @valid_mimetypes ) {
+ unless ( grep { $_ eq $mimetype } @valid_mimetypes ) {
push @messages, { type => 'alert', code => 'invalid_mimetype' };
$op = '';
}
my $preview_is_available = 0;
if ($code) {
- $preview_is_available = grep {/^$code$/} qw( CHECKIN CHECKOUT HOLD_SLIP );
+ $preview_is_available = grep {$_ eq $code } qw( CHECKIN CHECKOUT HOLD_SLIP );
}
$template->param(
for my $field ( qw/surname firstname branchcode categorycode streetnumber address address2 city state zipcode country email phone mobile sort1 sort2 dateenrolled dateexpiry borrowernotes opacnote/ ) {
my $value = $input->param($field);
$infos->{$field} = $value if $value;
- $infos->{$field} = "" if grep { /^$field$/ } @disabled;
+ $infos->{$field} = "" if grep { $_ eq $field } @disabled;
}
for my $field ( qw( dateenrolled dateexpiry debarred ) ) {
# If this borrower is not in the category of this attribute, we don't want to modify this attribute
++$i and next if $attr_type->{category_code} and $attr_type->{category_code} ne $borrower_categorycode;
my $valuename = "attr" . $i . "_value";
- if ( grep { /^$valuename$/ } @disabled ) {
+ if ( grep { $_ eq $valuename } @disabled ) {
# The attribute is disabled, we remove it for this borrower !
eval {
C4::Members::Attributes::DeleteBorrowerAttribute( $borrowernumber, $attribute );
if ( $shelf ) {
$op = $referer;
my $sortfield = $query->param('sortfield');
- $sortfield = 'title' unless grep {/^$sortfield$/}qw( title author copyrightdate itemcallnumber dateadded );
+ $sortfield = 'title' unless grep { $_ eq $sortfield } qw( title author copyrightdate itemcallnumber dateadded );
if ( $shelf->can_be_managed( $loggedinuser ) ) {
$shelf->shelfname( scalar $query->param('shelfname') );
$shelf->sortfield( $sortfield );
if ( $shelf ) {
if ( $shelf->can_be_viewed( $loggedinuser ) ) {
my $sortfield = $query->param('sortfield') || $shelf->sortfield || 'title'; # Passed in sorting overrides default sorting
- $sortfield = 'title' unless grep $_ eq $sortfield, qw( title author copyrightdate itemcallnumber dateadded );
+ $sortfield = 'title' unless grep { $_ eq $sortfield } qw( title author copyrightdate itemcallnumber dateadded );
my $direction = $query->param('direction') || 'asc';
$direction = 'asc' if $direction ne 'asc' and $direction ne 'desc';
my ( $rows, $page );