Koha/C4/Utils/DataTables.pm
Jonathan Druart f35571410b Bug 28069: (bug 27715 follow-up) Fix sort for lists
Sort functionality has been broken by bug 27715. We need to specify the
table.column in the datatable init

Note that "count" needs to be handled separately (which is a bit dirty
but cannot find something better)

Test plan:
Create some lists, add contents, change owner and dates
Sort using the different attributes and confirm that it's now working

Signed-off-by: Séverine QUEUNE <severine.queune@bulac.fr>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
2021-04-16 16:20:50 +02:00

154 lines
4.6 KiB
Perl

package C4::Utils::DataTables;
# Copyright 2011 BibLibre
#
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.
use Modern::Perl;
require Exporter;
use vars qw(@ISA @EXPORT);
BEGIN {
@ISA = qw(Exporter);
@EXPORT = qw(dt_build_orderby dt_get_params);
}
=head1 NAME
! DEPRECATED - This module is deprecated, the REST API route and REST API Datatables wrapper must be used instead!
C4::Utils::DataTables - Utility subs for building query when DataTables source is AJAX
=head1 SYNOPSYS
use CGI qw ( -utf8 );
use C4::Context;
use C4::Utils::DataTables;
my $input = new CGI;
my $vars = $input->Vars;
my $query = qq{
SELECT surname, firstname
FROM borrowers
WHERE borrowernumber = ?
};
$query .= dt_build_orderby($vars);
$query .= " LIMIT ?,? ";
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare($query);
$sth->execute(
$vars->{'borrowernumber'},
@$having_params,
$vars->{'iDisplayStart'},
$vars->{'iDisplayLength'}
);
...
=head1 DESCRIPTION
This module provide two utility functions to build a part of the SQL query,
depending on DataTables parameters.
One function build the 'ORDER BY' part, and the other the 'HAVING' part.
=head1 FUNCTIONS
=head2 dt_build_orderby
my $orderby = dt_build_orderby($dt_param);
This function takes a reference to a hash containing DataTables parameters
and build the corresponding 'ORDER BY' clause.
This hash must contains the following keys:
iSortCol_N, where N is a number from 0 to the number of columns to sort on minus 1
sSortDir_N is the sorting order ('asc' or 'desc) for the corresponding column
mDataProp_N is a mapping between the column index, and the name of a SQL field
=cut
sub dt_build_orderby {
my $param = shift;
my $i = 0;
my @orderbys;
my $dbh = C4::Context->dbh;
while(exists $param->{'iSortCol_'.$i}){
my $iSortCol = $param->{'iSortCol_'.$i};
my $sSortDir = $param->{'sSortDir_'.$i};
my $mDataProp = $param->{'mDataProp_'.$iSortCol};
my @sort_fields = $param->{$mDataProp.'_sorton'}
? split(' ', $param->{$mDataProp.'_sorton'})
: ();
if(@sort_fields > 0) {
push @orderbys, "$_ $sSortDir" foreach (@sort_fields);
} else {
push @orderbys, "$mDataProp $sSortDir";
}
$i++;
}
return unless @orderbys;
my @sanitized_orderbys;
# Trick for virtualshelves, should not be extended
push @sanitized_orderbys, 'count asc' if grep {$_ eq 'count asc'} @orderbys;
push @sanitized_orderbys, 'count desc' if grep {$_ eq 'count desc'} @orderbys;
# Must be "branches.branchname asc", "borrowers.firstname desc", etc.
@orderbys = grep { /^\w+\.\w+ (asc|desc)$/ } @orderbys;
for my $orderby (@orderbys) {
my ($identifier, $direction) = split / /, $orderby, 2;
my ($table, $column) = split /\./, $identifier, 2;
my $sanitized_identifier = $dbh->quote_identifier(undef, $table, $column);
my $sanitized_direction = $direction eq 'asc' ? 'ASC' : 'DESC';
push @sanitized_orderbys, "$sanitized_identifier $sanitized_direction";
}
return " ORDER BY " . join(',', @sanitized_orderbys) . " " if @sanitized_orderbys;
}
=head2 dt_get_params
my %dtparam = = dt_get_params( $input )
This function takes a reference to a new CGI object.
It prepares a hash containing Datatable parameters.
=cut
sub dt_get_params {
my $input = shift;
my %dtparam;
my $vars = $input->Vars;
foreach(qw/ iDisplayStart iDisplayLength iColumns sSearch bRegex iSortingCols sEcho /) {
$dtparam{$_} = $input->param($_);
}
foreach(grep /(?:_sorton|_filteron)$/, keys %$vars) {
$dtparam{$_} = $vars->{$_};
}
for(my $i=0; $i<$dtparam{'iColumns'}; $i++) {
foreach(qw/ bSearchable sSearch bRegex bSortable iSortCol mDataProp sSortDir /) {
my $key = $_ . '_' . $i;
$dtparam{$key} = $input->param($key) if defined $input->param($key);
}
}
return %dtparam;
}
1;