1 |
|
package SL::Template::Plugin::MultiColumnIterator;
|
2 |
|
|
3 |
|
use base 'Template::Plugin';
|
4 |
|
use Template::Constants;
|
5 |
|
use Template::Exception;
|
6 |
|
use Template::Iterator;
|
7 |
|
use SL::LXDebug;
|
8 |
|
use Data::Dumper;
|
9 |
|
|
10 |
|
use strict;
|
11 |
|
|
12 |
|
our $AUTOLOAD;
|
13 |
|
|
14 |
|
sub new {
|
15 |
|
$main::lxdebug->enter_sub();
|
16 |
|
my $class = shift;
|
17 |
|
my $context = shift;
|
18 |
|
my $data = shift || [ ];
|
19 |
|
my $dim = shift || 1;
|
20 |
|
|
21 |
|
$dim = 1 if $dim < 1;
|
22 |
|
|
23 |
|
use vars qw(@ISA);
|
24 |
|
push @ISA, "Template::Iterator";
|
25 |
|
|
26 |
|
if (ref $data eq 'HASH') {
|
27 |
|
# map a hash into a list of { key => ???, value => ??? } hashes,
|
28 |
|
# one for each key, sorted by keys
|
29 |
|
$data = [ map { { key => $_, value => $data->{ $_ } } }
|
30 |
|
sort keys %$data ];
|
31 |
|
}
|
32 |
|
elsif (UNIVERSAL::can($data, 'as_list')) {
|
33 |
|
$data = $data->as_list();
|
34 |
|
}
|
35 |
|
elsif (ref $data ne 'ARRAY') {
|
36 |
|
# coerce any non-list data into an array reference
|
37 |
|
$data = [ $data ] ;
|
38 |
|
}
|
39 |
|
|
40 |
|
$main::lxdebug->leave_sub();
|
41 |
|
|
42 |
|
bless {
|
43 |
|
_DATA => $data,
|
44 |
|
_ERROR => '',
|
45 |
|
_DIM => $dim,
|
46 |
|
}, $class;
|
47 |
|
}
|
48 |
|
|
49 |
|
|
50 |
|
sub get_first {
|
51 |
|
$main::lxdebug->enter_sub();
|
52 |
|
my $self = shift;
|
53 |
|
my $data = $self->{ _DATA };
|
54 |
|
my $dim = $self->{ _DIM };
|
55 |
|
|
56 |
|
$self->{ _DATASET } = $self->{ _DATA };
|
57 |
|
my $size = int ((scalar @$data - 1) / $dim) + 1;
|
58 |
|
my $index = 0;
|
59 |
|
|
60 |
|
return (undef, Template::Constants::STATUS_DONE) unless $size;
|
61 |
|
|
62 |
|
# initialise various counters, flags, etc.
|
63 |
|
@$self{ qw( SIZE MAX INDEX COUNT FIRST LAST ) } = ( $size, $size - 1, $index, 1, 1, $size > 1 ? 0 : 1, undef );
|
64 |
|
@$self{ qw( PREV ) } = ( undef );
|
65 |
|
$$self{ qw( NEXT ) } = [ @{ $self->{ _DATASET } }[ map { $index + 1 + $_ * $size } 0 .. ($dim - 1) ] ];
|
66 |
|
|
67 |
|
$main::lxdebug->leave_sub();
|
68 |
|
return [ @{ $self->{ _DATASET } }[ map { $index + $_ * $size } 0 .. ($dim - 1) ] ];
|
69 |
|
}
|
70 |
|
|
71 |
|
sub get_next {
|
72 |
|
$main::lxdebug->enter_sub();
|
73 |
|
my $self = shift;
|
74 |
|
my ($max, $index) = @$self{ qw( MAX INDEX ) };
|
75 |
|
my $data = $self->{ _DATASET };
|
76 |
|
my $dim = $self->{ _DIM };
|
77 |
|
my $size = $self->{ SIZE };
|
78 |
|
|
79 |
|
# warn about incorrect usage
|
80 |
|
unless (defined $index) {
|
81 |
|
my ($pack, $file, $line) = caller();
|
82 |
|
warn("iterator get_next() called before get_first() at $file line $line\n");
|
83 |
|
return (undef, Template::Constants::STATUS_DONE); ## RETURN ##
|
84 |
|
}
|
85 |
|
|
86 |
|
# if there's still some data to go...
|
87 |
|
if ($index < $max) {
|
88 |
|
# update counters and flags
|
89 |
|
$index++;
|
90 |
|
@$self{ qw( INDEX COUNT FIRST LAST ) } = ( $index, $index + 1, 0, $index == $max ? 1 : 0 );
|
91 |
|
$$self{ qw( PREV ) } = [ @{ $self->{ _DATASET } }[ map { $index - 1 + $_ * $size } 0 .. ($dim - 1) ] ];
|
92 |
|
$$self{ qw( NEXT ) } = [ @{ $self->{ _DATASET } }[ map { $index + 1 + $_ * $size } 0 .. ($dim - 1) ] ];
|
93 |
|
$main::lxdebug->leave_sub();
|
94 |
|
return [ @{ $self->{ _DATASET } }[ map { $index + $_ * $size } 0 .. ($dim - 1) ] ];
|
95 |
|
}
|
96 |
|
else {
|
97 |
|
$main::lxdebug->leave_sub();
|
98 |
|
return (undef, Template::Constants::STATUS_DONE); ## RETURN ##
|
99 |
|
}
|
100 |
|
}
|
101 |
|
|
102 |
|
sub get_all {
|
103 |
|
my $self = shift;
|
104 |
|
my ($max, $index, $dim, $size) = @$self{ qw( MAX INDEX _DIM SIZE) };
|
105 |
|
my (@data, $i);
|
106 |
|
|
107 |
|
# if there's still some data to go...
|
108 |
|
if ($index < $max) {
|
109 |
|
$index++;
|
110 |
|
@data = map do{ !($i = $_) || +[ @{ $self->{ _DATASET } }[ map { $i + $_ * $size } 0 .. ($dim - 1) ] ] }, $index .. $max;
|
111 |
|
# update counters and flags
|
112 |
|
@$self{ qw( INDEX COUNT FIRST LAST ) } = ( $max, $max + 1, 0, 1 );
|
113 |
|
$main::lxdebug->leave_sub();
|
114 |
|
return \@data; ## RETURN ##
|
115 |
|
}
|
116 |
|
else {
|
117 |
|
$main::lxdebug->leave_sub();
|
118 |
|
return (undef, Template::Constants::STATUS_DONE); ## RETURN ##
|
119 |
|
}
|
120 |
|
}
|
121 |
|
|
122 |
|
sub AUTOLOAD {
|
123 |
|
my $self = shift;
|
124 |
|
my $item = $AUTOLOAD;
|
125 |
|
$item =~ s/.*:://;
|
126 |
|
return if $item eq 'DESTROY';
|
127 |
|
|
128 |
|
# alias NUMBER to COUNT for backwards compatability
|
129 |
|
$item = 'COUNT' if $item =~ /NUMBER/i;
|
130 |
|
|
131 |
|
return $self->{ uc $item };
|
132 |
|
}
|
133 |
|
|
134 |
|
sub dump {
|
135 |
|
$main::lxdebug->enter_sub();
|
136 |
|
my $self = shift;
|
137 |
|
$main::lxdebug->leave_sub();
|
138 |
|
return join('',
|
139 |
|
"<pre>",
|
140 |
|
" Data: ", Dumper($self->{ _DATA }), "\n",
|
141 |
|
" Index: ", $self->{ INDEX }, "\n",
|
142 |
|
"Number: ", $self->{ NUMBER }, "\n",
|
143 |
|
" Max: ", $self->{ MAX }, "\n",
|
144 |
|
" Size: ", $self->{ SIZE }, "\n",
|
145 |
|
" First: ", $self->{ FIRST }, "\n",
|
146 |
|
" Last: ", $self->{ LAST }, "\n",
|
147 |
|
"\n",
|
148 |
|
"</pre>"
|
149 |
|
);
|
150 |
|
}
|
151 |
|
|
152 |
|
sub index {
|
153 |
|
$main::lxdebug->enter_sub();
|
154 |
|
my ($self) = @_;
|
155 |
|
$main::lxdebug->leave_sub();
|
156 |
|
return $self->{ INDEX };
|
157 |
|
}
|
158 |
|
|
159 |
|
sub number {
|
160 |
|
$main::lxdebug->enter_sub();
|
161 |
|
my ($self) = @_;
|
162 |
|
$main::lxdebug->leave_sub();
|
163 |
|
return $self->{ NUMBER };
|
164 |
|
}
|
165 |
|
|
166 |
|
sub count {
|
167 |
|
$main::lxdebug->enter_sub();
|
168 |
|
my ($self) = @_;
|
169 |
|
$main::lxdebug->leave_sub();
|
170 |
|
return $self->{ COUNT };
|
171 |
|
}
|
172 |
|
sub max {
|
173 |
|
$main::lxdebug->enter_sub();
|
174 |
|
my ($self) = @_;
|
175 |
|
$main::lxdebug->leave_sub();
|
176 |
|
return $self->{ MAX };
|
177 |
|
}
|
178 |
|
|
179 |
|
sub size {
|
180 |
|
$main::lxdebug->enter_sub();
|
181 |
|
my ($self) = @_;
|
182 |
|
$main::lxdebug->leave_sub();
|
183 |
|
return $self->{ SIZE };
|
184 |
|
}
|
185 |
|
|
186 |
|
sub first {
|
187 |
|
$main::lxdebug->enter_sub();
|
188 |
|
my ($self) = @_;
|
189 |
|
$main::lxdebug->leave_sub();
|
190 |
|
return $self->{ FIRST };
|
191 |
|
}
|
192 |
|
|
193 |
|
sub last {
|
194 |
|
$main::lxdebug->enter_sub();
|
195 |
|
my ($self) = @_;
|
196 |
|
$main::lxdebug->leave_sub();
|
197 |
|
return $self->{ LAST};
|
198 |
|
}
|
199 |
|
|
200 |
|
1;
|
Alten Code entfernt (MultiColumnIterator)