Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Applied/reworked a patch to allow list.sort to sort on multiple fields

git-svn-id: svn://svn.tt2.org/tt/Template2/trunk@1245 d5a88997-0a34-4036-9ed2-92fb5d660d91
  • Loading branch information...
commit dfee7eca0701c9effc7d35eaacc8a431c96645ee 1 parent af22f8c
@abw authored
View
8 Changes
@@ -25,6 +25,14 @@
inside nested loops.
https://rt.cpan.org/Ticket/Display.html?id=40887
+* Fixed a bug in Template::Plugin::Filter that was causing the weakened
+ $self reference in a dynamic filter closure to be garbage collected
+ too soon.
+ https://rt.cpan.org/Ticket/Display.html?id=46691
+
+* Applied patch to allow list.sort to sort on multiple fields.
+ https://rt.cpan.org/Ticket/Display.html?id=40637
+
#-----------------------------------------------------------------------
# Version 2.21_01 - 4th July 2009
View
7 lib/Template/Manual/VMethods.pod
@@ -420,6 +420,13 @@ method will be called to return a comparison value.
In the example, the C<books> list can contains hash references with
an C<author> key or objects with an C<author> method.
+You can also specify multiple sort keys.
+
+ [% library = books.sort('author', 'title') %]
+
+In this case the books will be sorted primarily by author. If two or more
+books have authors with the same name then they will be sorted by title.
+
=head2 unshift(item), push(item)
The C<push()> method adds an item or items to the end of list.
View
59 lib/Template/VMethods.pm
@@ -23,6 +23,7 @@ package Template::VMethods;
use strict;
use warnings;
+use Scalar::Util 'blessed';
require Template::Stash;
our $VERSION = 2.16;
@@ -449,19 +450,34 @@ sub list_join {
map { defined $_ ? $_ : '' } @$list);
}
+sub _list_sort_make_key {
+ my ($item, $fields) = @_;
+ my @keys;
+
+ if (ref($item) eq 'HASH') {
+ @keys = map { $item->{ $_ } } @$fields;
+ }
+ elsif (blessed $item) {
+ @keys = map { $item->can($_) ? $item->$_() : $item } @$fields;
+ }
+ else {
+ @keys = $item;
+ }
+
+ # ugly hack to generate a single string using a delimiter that is
+ # unlikely (but not impossible) to be found in the wild.
+ return lc join('/*^UNLIKELY^*/', map { defined $_ ? $_ : '' } @keys);
+}
+
sub list_sort {
- no warnings;
- my ($list, $field) = @_;
- return $list unless @$list > 1; # no need to sort 1 item lists
- return [
- $field # Schwartzian Transform
- ? map { $_->[0] } # for case insensitivity
- sort { $a->[1] cmp $b->[1] }
- map { [ $_, lc(ref($_) eq 'HASH'
- ? $_->{ $field } :
- UNIVERSAL::can($_, $field)
- ? $_->$field() : $_) ] }
- @$list
+ my ($list, @fields) = @_;
+ return $list unless @$list > 1; # no need to sort 1 item lists
+ return [
+ @fields # Schwartzian Transform
+ ? map { $_->[0] } # for case insensitivity
+ sort { $a->[1] cmp $b->[1] }
+ map { [ $_, _list_sort_make_key($_, \@fields) ] }
+ @$list
: map { $_->[0] }
sort { $a->[1] cmp $b->[1] }
map { [ $_, lc $_ ] }
@@ -470,21 +486,18 @@ sub list_sort {
}
sub list_nsort {
- my ($list, $field) = @_;
+ my ($list, @fields) = @_;
return $list unless @$list > 1; # no need to sort 1 item lists
return [
- $field # Schwartzian Transform
+ @fields # Schwartzian Transform
? map { $_->[0] } # for case insensitivity
sort { $a->[1] <=> $b->[1] }
- map { [ $_, lc(ref($_) eq 'HASH'
- ? $_->{ $field } :
- UNIVERSAL::can($_, $field)
- ? $_->$field() : $_) ] }
- @$list
- : map { $_->[0] }
- sort { $a->[1] <=> $b->[1] }
- map { [ $_, lc $_ ] }
- @$list,
+ map { [ $_, _list_sort_make_key($_, \@fields) ] }
+ @$list
+ : map { $_->[0] }
+ sort { $a->[1] <=> $b->[1] }
+ map { [ $_, lc $_ ] }
+ @$list,
];
}
View
29 t/vmethods/list.t
@@ -39,16 +39,23 @@ $Template::Config::STASH = 'Template::Stash';
package My::Object;
sub new {
- my ($class, $name) = @_;
+ my ($class, $name, $extra) = @_;
bless {
- _NAME => $name,
+ _NAME => $name,
+ _EXTRA => $extra,
}, $class;
}
+
sub name {
my $self = shift;
return $self->{ _NAME };
}
+sub extra {
+ my $self = shift;
+ return $self->{ _EXTRA };
+}
+
#------------------------------------------------------------------------
package main;
@@ -86,6 +93,12 @@ my $params = {
groceries => { 'Flour' => 3, 'Milk' => 1, 'Peanut Butter' => 21 },
names => [ map { My::Object->new($_) }
qw( Tom Dick Larry ) ],
+ more_names => [
+ My::Object->new('Smith', 'William'),
+ My::Object->new('Smith', 'Andrew'),
+ My::Object->new('Jones', 'Peter'),
+ My::Object->new('Jones', 'Mark'),
+ ],
numbers => [ map { My::Object->new($_) }
qw( 1 02 10 12 021 ) ],
duplicates => [ 1, 1, 2, 2, 3, 3, 4, 4, 5, 5],
@@ -166,6 +179,7 @@ Richard
Larry
Tom
+-- start --
-- test --
[% FOREACH obj = names.sort('name') -%]
[% obj.name +%]
@@ -176,6 +190,17 @@ Larry
Tom
-- test --
+[% FOREACH obj IN more_names.sort('name', 'extra') -%]
+[% obj.extra %] [% obj.name %]
+[% END %]
+-- expect --
+Mark Jones
+Peter Jones
+Andrew Smith
+William Smith
+-- stop --
+
+-- test --
[% FOREACH obj = numbers.sort('name') -%]
[% obj.name +%]
[% END %]
Please sign in to comment.
Something went wrong with that request. Please try again.