X-Git-Url: http://wagnertech.de/gitweb/gitweb.cgi/mfinanz.git/blobdiff_plain/dbd7b379d8bd8e0dcd4edb3543483468feeaf386..7647d46:/SL/DB/Helper/ActsAsList.pm diff --git a/SL/DB/Helper/ActsAsList.pm b/SL/DB/Helper/ActsAsList.pm index ade8fdc10..ce927bba4 100644 --- a/SL/DB/Helper/ActsAsList.pm +++ b/SL/DB/Helper/ActsAsList.pm @@ -3,7 +3,7 @@ package SL::DB::Helper::ActsAsList; use strict; use parent qw(Exporter); -our @EXPORT = qw(move_position_up move_position_down); +our @EXPORT = qw(move_position_up move_position_down reorder_list); use Carp; @@ -33,15 +33,38 @@ sub move_position_down { do_move($self, 'down'); } +sub reorder_list { + my ($class_or_self, @ids) = @_; + + return 1 unless @ids; + + my $self = ref($class_or_self) ? $class_or_self : $class_or_self->new; + my $column = column_name($self); + my $result = $self->db->do_transaction(sub { + my $query = qq|UPDATE | . $self->meta->table . qq| SET ${column} = ? WHERE id = ?|; + my $sth = $self->db->dbh->prepare($query) || die $self->db->dbh->errstr; + + foreach my $new_position (1 .. scalar(@ids)) { + $sth->execute($new_position, $ids[$new_position - 1]) || die $sth->errstr; + } + + $sth->finish; + }); + + return $result; +} + # # Helper functions # sub set_position { my ($self) = @_; - if (!defined $self->position) { - my $max_position = $self->db->dbh->selectrow_arrayref(qq|SELECT COALESCE(max(position), 0) FROM | . $self->meta->table)->[0]; - $self->position($max_position + 1); + my $column = column_name($self); + + if (!defined $self->$column) { + my $max_position = $self->db->dbh->selectrow_arrayref(qq|SELECT COALESCE(max(${column}), 0) FROM | . $self->meta->table)->[0]; + $self->$column($max_position + 1); } return 1; @@ -49,11 +72,12 @@ sub set_position { sub remove_position { my ($self) = @_; + my $column = column_name($self); $self->load; - if (defined $self->position) { - $self->_get_manager_class->update_all(set => { position => \'position - 1' }, - where => [ position => { gt => $self->position } ]); + if (defined $self->$column) { + $self->_get_manager_class->update_all(set => { $column => \"${column} - 1" }, + where => [ $column => { gt => $self->$column } ]); } return 1; @@ -61,19 +85,25 @@ sub remove_position { sub do_move { my ($self, $direction) = @_; + my $column = column_name($self); croak "Object has not been saved yet" unless $self->id; - croak "No position set yet" unless defined $self->position; + croak "No position set yet" unless defined $self->$column; my ($comp_sql, $comp_rdbo, $min_max, $plus_minus) = $direction eq 'up' ? ('<', 'ge', 'max', '+') : ('>', 'le', 'min', '-'); - my $new_position = $self->db->dbh->selectrow_arrayref(qq|SELECT ${min_max}(position) FROM | . $self->meta->table . qq| WHERE position ${comp_sql} | . $self->position)->[0]; + my $new_position = $self->db->dbh->selectrow_arrayref(qq|SELECT ${min_max}(${column}) FROM | . $self->meta->table . qq| WHERE ${column} ${comp_sql} | . $self->$column)->[0]; return undef unless defined $new_position; - $self->_get_manager_class->update_all(set => { position => $self->position }, - where => [ position => $new_position ]); - $self->update_attributes(position => $new_position); + $self->_get_manager_class->update_all(set => { $column => $self->$column }, + where => [ $column => $new_position ]); + $self->update_attributes($column => $new_position); +} + +sub column_name { + my ($self) = @_; + return $self->can('sortkey') ? 'sortkey' : 'position'; } 1; @@ -85,7 +115,8 @@ __END__ =head1 NAME -SL::DB::Helper::ActsAsList - Mixin for managing ordered items by a column I +SL::DB::Helper::ActsAsList - Mixin for managing ordered items by a +column I or I =head1 SYNOPSIS @@ -107,9 +138,10 @@ SL::DB::Helper::ActsAsList - Mixin for managing ordered items by a column Idelete This mixin assumes that the mixing package's table contains a column -called C. This column is set automatically upon saving the -object if it hasn't been set already. If it hasn't then it will be set -to the maximum position used in the table plus one. +called C or C (for legacy tables). This column is +set automatically upon saving the object if it hasn't been set +already. If it hasn't then it will be set to the maximum position used +in the table plus one. When the object is deleted all positions greater than the object's old position are decreased by one. @@ -128,6 +160,22 @@ regarding their sort order by exchanging their C values. Swaps the object with the object one step below the current one regarding their sort order by exchanging their C values. +=item C + +Re-orders the objects given in C<@ids> by their position in C<@ids> by +updating all of their positional columns. Each element in +C<@positions> must be the ID of an object. The new position is the +ID's index inside C<@ids> plus one (meaning the first element's new +position will be 1 and not 0). + +This works by executing SQL "UPDATE" statements directly. + +Returns the result of the whole transaction (trueish in case of +success). + +This method can be called both as a class method or an instance +method. + =back =head1 BUGS