Revision 608

Date:
2016/11/01 18:52:39
Author:
ahitrov
Revision Log:
Document advanced sorting.

Files:

Legend:

 
Added
 
Removed
 
Modified
  • utf8/core/lib/Contenido/Section.pm

     
    64 64 class_table()->new();
    65 65 }
    66 66
    67 sub pre_store {
    68 my $self = shift;
    69 67
    70 if ( $self->id && !$self->{__light} ) {
    71 ### Autofill or autoflush documents order if applicable
    72 if ( $self->_sorted && !$self->_sorted_order ) {
    73 my %opts;
    74 if ( $self->default_document_class ) {
    75 $opts{class} = $self->default_document_class;
    76 } elsif ( $self->default_table_class ) {
    77 $opts{table} = $self->default_table_class;
    78 } else {
    79 $opts{table} = 'Contenido::SQL::DocumentTable';
    80 }
    81 if ( $self->order_by ) {
    82 $opts{order_by} = $self->order_by;
    83 }
    84 if ( $self->filters ) {
    85 no strict 'vars';
    86 my $filters = eval($self->filters);
    87 if ($@) {
    88 warn "Bad filter: " . $self->filters . " in section " . $self->id;
    89 } elsif (ref $filters eq 'HASH') {
    90 while ( my ($key, $val) = each %$filters ) {
    91 $opts{$key} = $val;
    92 }
    93 }
    94 }
    95 my $ids = $keeper->get_documents( s => $self->id, %opts, ids => 1, return_mode => 'array_ref' );
    96 $self->_sorted_order( join(',', @$ids) );
    97 } elsif ( !$self->_sorted && $self->_sorted_order ) {
    98 $self->_sorted_order( undef );
    99 }
    100 }
    101
    102 1;
    103 }
    104
    105 68 #доработка метода store
    106 69 sub store {
    107 my $self=shift;
    70 my $self = shift;
    71 my (%opts) = @_;
    108 72
    109 73 #для новосозданных секций ставим новый sorder
    110 unless ($self->{id}) {
    111 my ($sorder) = $self->keeper->SQL->selectrow_array("select max(sorder) from ".$self->class_table->db_table(), {});
    112 $self->{sorder} = $sorder + 1;
    74 if ( $self->{id} ) {
    75 my $without_sort = delete $opts{without_sort};
    76 unless ( $without_sort || $self->{__light} ) {
    77 ### Autofill or autoflush documents order if applicable
    78 if ( $self->_sorted ) {
    79 my $ids = $self->_get_document_order;
    80 $self->_sorted_order( join(',', @$ids) );
    81 } elsif ( !$self->_sorted && $self->_sorted_order ) {
    82 $self->_sorted_order( undef );
    83 }
    84 }
    85 } else {
    86 my ($sorder) = $self->keeper->SQL->selectrow_array("select max(sorder) from ".$self->class_table->db_table(), {});
    87 $self->{sorder} = $sorder + 1;
    113 88 }
    114 89
    115 90 return $self->SUPER::store();
     
    223 198 }
    224 199
    225 200
    201 sub _get_document_order {
    202 my ($self) = shift;
    226 203
    204 my @order = $self->_sorted_order ? split( /,/, $self->_sorted_order ) : ();
    205
    206 my %opts;
    207 if ( $self->default_document_class ) {
    208 $opts{class} = $self->default_document_class;
    209 } elsif ( $self->default_table_class ) {
    210 $opts{table} = $self->default_table_class;
    211 } else {
    212 $opts{table} = 'Contenido::SQL::DocumentTable';
    213 }
    214 if ( $self->order_by ) {
    215 $opts{order_by} = $self->order_by;
    216 }
    217 if ( $self->filters ) {
    218 no strict 'vars';
    219 my $filters = eval($self->filters);
    220 if ($@) {
    221 warn "Bad filter: " . $self->filters . " in section " . $self->id;
    222 } elsif (ref $filters eq 'HASH') {
    223 while ( my ($key, $val) = each %$filters ) {
    224 $opts{$key} = $val;
    225 }
    226 }
    227 }
    228 my $ids = $keeper->get_documents( s => $self->id, %opts, ids => 1, return_mode => 'array_ref' );
    229 my %ids = map { $_ => 1 } @$ids;
    230 my @new_order;
    231 foreach my $iid ( @order ) {
    232 if ( exists $ids{$iid} ) {
    233 push @new_order, $iid;
    234 delete $ids{$iid};
    235 }
    236 }
    237 foreach my $iid ( @$ids ) {
    238 if ( exists $ids{$iid} ) {
    239 push @new_order, $iid;
    240 delete $ids{$iid};
    241 }
    242 }
    243 return \@new_order;
    244 }
    245
    246
    227 247 # ----------------------------------------------------------------------------
    228 248 # Метод для перемещение секции вверх/вниз по рубрикатору (изменение
    229 249 # sorder)...
     
    289 309 # $doc->dmove($doc_id, $direction); Направление задается строкой 'up'/'down'
    290 310 # ----------------------------------------------------------------------------
    291 311 sub dmove {
    292 my ($self, $doc_id, $direction) = @_;
    312 my ($self, $doc_id, $direction, $anchor) = @_;
    293 313 do { $log->error("Метод ->dmove() можно вызывать только у объектов, но не классов"); die } unless ref($self);
    294 314
    295 315 return undef if ($self->keeper->state->readonly());
     
    300 320 unless (exists($self->{id}) && ($self->{id} > 0));
    301 321
    302 322 $direction = lc($direction);
    303 if ( ($direction ne 'up') && ($direction ne 'down') ) { $log->warning("Направление перемещения документа задано неверно"); return undef };
    323 unless ( $direction eq 'up' || $direction eq 'down' || $direction eq 'first' || $direction eq 'last' || $direction eq 'before' || $direction eq 'after' ) {
    324 $log->warning("Направление перемещения документа задано неверно"); return undef
    325 };
    326 my $anchor_flag = 0;
    327 if ( ($direction eq 'before' || $direction eq 'after') && !$anchor ) {
    328 $log->warning("Неверный вызов функции dmove для направления '$direction'. Необходимо указать дополнительно id в списке документов"); return undef;
    329 } elsif ( $direction eq 'before' || $direction eq 'after' ) {
    330 $anchor_flag = 1;
    331 }
    304 332
    305 my $sorder_;
    306 333 if ($self->_sorted()) {
    307 my @ids = $keeper->get_documents( ids =>1, s => $self->id(),
    308 ($self->default_document_class ? (class => $self->default_document_class) : $self->default_table_class ? (table => $self->default_table_class) : ()),
    309 order => ['date', undef], light => 1
    310 );
    311 my %ids = map { $_ => 1 } @ids;
    312 unless ($self->{_sorted_order}) {
    313 $self->{_sorted_order} = join ',', @ids;
    314 }
    334 my $order = $self->_get_document_order;
    335 my @new_order;
    336 if ( $direction eq 'first' ) {
    337 push @new_order, $doc_id;
    338 }
    339 for ( my $i = 0; $i < scalar @$order; $i++ ) {
    340 if ( ($direction eq 'first' || $direction eq 'last' || $direction eq 'after' || $direction eq 'before') && $order->[$i] == $doc_id ) {
    341 next;
    342 } elsif ( $direction eq 'up' && $order->[$i] == $doc_id ) {
    343 if ( $i ) {
    344 my $id = pop @new_order;
    345 push @new_order, ($doc_id, $id);
    346 } else {
    347 push @new_order, $doc_id;
    348 }
    349 } elsif ( $direction eq 'down' && $order->[$i] == $doc_id ) {
    350 if ( $i < scalar(@$order) - 1 ) {
    351 push @new_order, ($order->[++$i], $doc_id);
    352 } else {
    353 push @new_order, $doc_id;
    354 }
    355 } elsif ( $direction eq 'before' && $order->[$i] == $anchor ) {
    356 push @new_order, ($doc_id, $order->[$i]);
    357 $anchor_flag = 0;
    358 } elsif ( $direction eq 'after' && $order->[$i] == $anchor ) {
    359 push @new_order, ($order->[$i], $doc_id);
    360 $anchor_flag = 0;
    361 } else {
    362 push @new_order, $order->[$i];
    363 }
    364 }
    365 if ( $anchor_flag ) {
    366 $log->warning("Неверный вызов функции dmove для направления '$direction'. Не найден якорь [$anchor]"); return undef;
    367 }
    368 if ( $direction eq 'last' ) {
    369 push @new_order, $doc_id;
    370 }
    315 371
    316 my @order = split(/,/, $self->{_sorted_order});
    317 @order = grep {
    318 my $res;
    319 if (exists $ids{$_}) {
    320 $res = 1;
    321 delete $ids{$_};
    322 }
    323 $res
    324 } @order;
    325
    326 push @order, keys %ids;
    327
    328 foreach my $i (0 .. $#order) {
    329 if ($order[$i] == $doc_id) {
    330 my $t;
    331 if ($direction eq 'up') {
    332 last if $i == 0;
    333 $t = $order[$i-1];
    334 $order[$i-1] = $order[$i];
    335 $order[$i] = $t;
    336 $sorder_ = $i - 1;
    337 last;
    338 } elsif ($direction eq 'down') {
    339 last if $i == $#order;
    340 $t = $order[$i+1];
    341 $order[$i+1] = $order[$i];
    342 $order[$i] = $t;
    343 $sorder_ = $i + 1;
    344 last;
    345 }
    346 }
    347 }
    348
    349 $self->{_sorted_order} = join ',', @order;
    350 $self->store();
    372 $self->{_sorted_order} = join ',', @new_order;
    373 $self->store( without_sort => 1 );
    351 374 } else {
    352 $log->warning("dmove called for section without enabled sorted feature... $self->{id}/$self->{class}");
    375 $log->warning("dmove called for section without enabled sorted feature... ".$self->id."/".$self->class);
    353 376 }
    354 377
    355 $self->{sorder} = $sorder_;
    356 378 return 1;
    357 379 }
    358 380