Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 06fd85e8

Von Sven Schöling vor etwa 17 Jahren hinzugefügt

  • ID 06fd85e8e7c7813fb15bdb9e8add12b6c78031ed
  • Vorgänger 468e86a6
  • Nachfolger 0a385d07

MultiColumnIterator

Verhält sich wie der normale Template::Iterator (siehe man Template::Iterator), akzeptiert aber einen zusätzlichen Parameter fuer eine Spaltenbreite.

Hat man Beispielsweise ein Array mit 11 Eintraegen und mochte diese auf 3 Zeilen im Template ausgeben, so gibt ein mit

[% USE miter = MultiColumnIterator(DATA, 3) %]

aufgerufener Iterator mit jeder Iteration ein Array von 4 Eintraegen zurueck, mit dem dann sequnziell die gewuenschte Sortierung ausgegeben werden kann.
Die Datensaetze werden in folgender Reihenfolge ausgegeben:

[ 1, 5, 9 ]
[ 2, 6, 10 ]
[ 3, 7, 11 ]
[ 4, 8, undef ]

Unterschiede anzeigen:

SL/Template/Plugin/MultiColumnIterator.pm
1
package SL::Template::Plugin::MultiColumnIterator;
2

  
3
use strict;
4
use base 'Template::Plugin';
5
use Template::Constants;
6
use Template::Exception;
7
use Template::Iterator;
8
use SL::LXDebug;
9
use Data::Dumper;
10

  
11
our $AUTOLOAD;
12

  
13
sub new {
14
    $main::lxdebug->enter_sub(); 
15
    my $class   = shift;
16
    my $context = shift;
17
    my $data    = shift || [ ];
18
    my $dim     = shift || 1;
19

  
20
    $dim        = 1 if $dim < 1;
21

  
22
    use vars qw(@ISA);
23
    push @ISA, "Template::Iterator";
24

  
25
    if (ref $data eq 'HASH') {
26
        # map a hash into a list of { key => ???, value => ??? } hashes,
27
        # one for each key, sorted by keys
28
        $data = [ map { { key => $_, value => $data->{ $_ } } }
29
                  sort keys %$data ];
30
    }
31
    elsif (UNIVERSAL::can($data, 'as_list')) {
32
        $data = $data->as_list();
33
    }
34
    elsif (ref $data ne 'ARRAY') {
35
        # coerce any non-list data into an array reference
36
        $data  = [ $data ] ;
37
    }
38

  
39
    $main::lxdebug->leave_sub(); 
40

  
41
    bless {
42
        _DATA  => $data,
43
        _ERROR => '',
44
        _DIM   => $dim,
45
    }, $class;
46
}
47

  
48

  
49
sub get_first {
50
    $main::lxdebug->enter_sub(); 
51
    my $self  = shift;
52
    my $data  = $self->{ _DATA };
53
    my $dim   = $self->{ _DIM  };
54

  
55
    $self->{ _DATASET } = $self->{ _DATA };
56
    my $size = int ((scalar @$data - 1) / $dim) + 1;
57
    my $index = 0;
58
    
59
    return (undef, Template::Constants::STATUS_DONE) unless $size;
60

  
61
    # initialise various counters, flags, etc.
62
    @$self{ qw( SIZE MAX INDEX COUNT FIRST LAST ) } = ( $size, $size - 1, $index, 1, 1, $size > 1 ? 0 : 1, undef );
63
    @$self{ qw( PREV ) } = ( undef );
64
    $$self{ qw( NEXT ) } = [ @{ $self->{ _DATASET }  }[ map { $index + 1 + $_ * $size } 0 .. ($dim - 1) ] ];
65

  
66
    $main::lxdebug->leave_sub(); 
67
    return [ @{ $self->{ _DATASET } }[ map { $index + $_ * $size } 0 .. ($dim - 1) ] ];
68
}
69

  
70
sub get_next {
71
    $main::lxdebug->enter_sub(); 
72
    my $self = shift;
73
    my ($max, $index) = @$self{ qw( MAX INDEX ) };
74
    my $data = $self->{ _DATASET };
75
    my $dim  = $self->{ _DIM  };
76
    my $size = $self->{ SIZE  };
77

  
78
    # warn about incorrect usage
79
    unless (defined $index) {
80
        my ($pack, $file, $line) = caller();
81
        warn("iterator get_next() called before get_first() at $file line $line\n");
82
        return (undef, Template::Constants::STATUS_DONE);   ## RETURN ##
83
    }
84

  
85
    # if there's still some data to go...
86
    if ($index < $max) {
87
        # update counters and flags
88
        $index++;
89
        @$self{ qw( INDEX COUNT FIRST LAST ) } = ( $index, $index + 1, 0, $index == $max ? 1 : 0 );
90
        $$self{ qw( PREV ) } = [ @{ $self->{ _DATASET } }[ map { $index - 1 + $_ * $size } 0 .. ($dim - 1) ] ];
91
        $$self{ qw( NEXT ) } = [ @{ $self->{ _DATASET } }[ map { $index + 1 + $_ * $size } 0 .. ($dim - 1) ] ];
92
        $main::lxdebug->leave_sub(); 
93
        return [ @{ $self->{ _DATASET } }[ map { $index + $_ * $size } 0 .. ($dim - 1) ] ];
94
    }
95
    else {
96
        $main::lxdebug->leave_sub(); 
97
        return (undef, Template::Constants::STATUS_DONE);   ## RETURN ##
98
    }
99
}
100

  
101
sub get_all {
102
    my $self = shift;
103
    my ($max, $index, $dim, $size) = @$self{ qw( MAX INDEX _DIM SIZE) };
104
    my (@data, $i);
105

  
106
    # if there's still some data to go...
107
    if ($index < $max) {
108
        $index++;
109
        @data = map do{ !($i = $_) || +[ @{ $self->{ _DATASET } }[ map { $i + $_ * $size } 0 .. ($dim - 1) ] ] }, $index .. $max;
110
        # update counters and flags
111
        @$self{ qw( INDEX COUNT FIRST LAST ) } = ( $max, $max + 1, 0, 1 );
112
        $main::lxdebug->leave_sub();
113
        return \@data;					    ## RETURN ##
114
    }
115
    else {
116
        $main::lxdebug->leave_sub();
117
        return (undef, Template::Constants::STATUS_DONE);   ## RETURN ##
118
    }
119
}
120

  
121
sub AUTOLOAD {
122
    my $self = shift;
123
    my $item = $AUTOLOAD;
124
    $item =~ s/.*:://;
125
    return if $item eq 'DESTROY';
126

  
127
    # alias NUMBER to COUNT for backwards compatability
128
    $item = 'COUNT' if $item =~ /NUMBER/i;
129

  
130
    return $self->{ uc $item };
131
}
132

  
133
sub dump {
134
    $main::lxdebug->enter_sub(); 
135
    my $self = shift;
136
    $main::lxdebug->leave_sub(); 
137
    return join('',
138
         "<pre>",
139
         "  Data: ", Dumper($self->{ _DATA  }), "\n",
140
         " Index: ", $self->{ INDEX  }, "\n",
141
         "Number: ", $self->{ NUMBER }, "\n",
142
         "   Max: ", $self->{ MAX    }, "\n",
143
         "  Size: ", $self->{ SIZE   }, "\n",
144
         " First: ", $self->{ FIRST  }, "\n",
145
         "  Last: ", $self->{ LAST   }, "\n",
146
         "\n",
147
         "</pre>"
148
     );
149
}
150

  
151
sub index {
152
  $main::lxdebug->enter_sub(); 
153
  my ($self) = @_;
154
  $self->{ INDEX };
155
  $main::lxdebug->leave_sub(); 
156
}
157

  
158
sub number {
159
  $main::lxdebug->enter_sub(); 
160
  my ($self) = @_;
161
  $self->{ NUMBER };
162
  $main::lxdebug->leave_sub(); 
163
}
164

  
165
sub max {
166
  $main::lxdebug->enter_sub(); 
167
  my ($self) = @_;
168
  $self->{ MAX };
169
  $main::lxdebug->leave_sub(); 
170
}
171

  
172
sub size {
173
  $main::lxdebug->enter_sub(); 
174
  my ($self) = @_;
175
  $self->{ SIZE };
176
  $main::lxdebug->leave_sub(); 
177
}
178

  
179
sub first {
180
  $main::lxdebug->enter_sub(); 
181
  my ($self) = @_;
182
  $self->{ FIRST };
183
  $main::lxdebug->leave_sub(); 
184
}
185

  
186
sub last {
187
  $main::lxdebug->enter_sub(); 
188
  my ($self) = @_;
189
  $self->{ LAST};
190
  $main::lxdebug->leave_sub(); 
191
}
192

  
193
1;

Auch abrufbar als: Unified diff