<% $json %> <%once> use JSON::XS; <%args> $id => undef $params => undef $return => 'json' $section => undef $build_html => 1 <%init> my %result; if ( ($return eq 'json' && $id && $id =~ /^\d+$/) || ($return eq 'hash' && ref $section) ) { $section = $keeper->get_section_by_id( $id ) unless ref $section; if ( ref $section ) { my %params; if ( ref $params eq 'HASH' ) { %params = %$params; } elsif ( ref $params eq 'ARRAY' ) { map { if ( ref $_ eq 'ARRAY' && scalar @$_ == 2 ) { $params{$_->[0]} = $_->[1]; } elsif ( $_ =~ /(.+?)=(.*)/ ) { $params{$1} = $2 } } @$params; } elsif ( $params ) { map { if ( $_ =~ /(.+?)=(.*)/ ) { $params{$1} = $2 } } split(/\&/, $params); } my $params_unclassed = join ('&', map { $_.'='.$params{$_} } grep { $_ ne 'class' } keys %params ); my $params_unsection = join ('&', map { $_.'='.$params{$_} } grep { $_ ne 's' } keys %params ); my %filter_params; $filter_params{use_section} = $params{use_section} if exists $params{use_section} && $params{use_section}; $filter_params{class} = $params{class} if exists $params{class} && $params{class}; $filter_params{alpha} = $params{alpha} if exists $params{alpha} && $params{alpha}; $filter_params{alpha_search} = $params{alpha_search} if exists $params{alpha_search} && $params{alpha_search}; $filter_params{search_by} = $params{search_by} if exists $params{search_by} && $params{search_by}; $filter_params{search} = $params{search} if exists $params{search} && $params{search}; $filter_params{p} = $params{p} if exists $params{p} && $params{p} > 1; $filter_params{s} = $params{id} if exists $params{id} && $params{id}; my $p = exists $params{p} && $params{p} ? $params{p} : 1; # Фильтры работают в любом случае... my $filter = $m->comp('/contenido/components/context.msn', name => 'filter'); my $profile = $m->comp('/contenido/components/context.msn', name => 'profile'); unless (defined $request->{section_accesses}->{$section->id}) { $request->{section_accesses}->{$section->id} = $user->get_section_access($section->id); } my $section_access = $request->{section_accesses}->{$section->id}; my (@documents, $total); my $s = $section->id; my $sorted = $section->_sorted(); $s .= ",$filter" if ($filter > 0); my %filter; my $nothing_found = 0; my %order = (!(exists $params{class} && $params{class}) && $section->order_by) ? (order_by => $section->order_by) : (order => ['date','direct']); if ( exists $params{alpha} and $params{alpha} ne '' ) { $filter{ilike} = 1; $filter{ $params{alpha_search} || 'name' } = $params{alpha}."%"; $order{order} = ['name','reverse']; delete $order{order_by}; } if ( exists $params{class} && $params{class} ) { $filter{class} = $params{class}; } elsif ( $section->default_document_class ) { $filter{class} = $section->default_document_class; } elsif ( $section->default_table_class ) { $filter{table} = $section->default_table_class; } $filter{s} = $s unless exists $params{class} && $params{class} && !(exists $params{use_section} && $params{use_section}); if ( exists $params{search_by} && $params{search_by} && exists $params{search} && defined $params{search} ) { my $doc_class = exists $params{class} && $params{class} ? $params{class} : $section->default_document_class; my $search = $params{search}; my $search_by = $params{search_by}; if ( $doc_class ) { my @props = $doc_class->new( $keeper )->structure(); my ($prop) = grep { $_->{attr} eq $search_by } @props if @props; if ( ref $prop && ($prop->{type} eq 'integer' || $prop->{type} eq 'checkbox' || (($prop->{type} eq 'pickup' || $prop->{type} eq 'lookup' || $prop->{type} eq 'status') && $search =~ /^\d+$/) || (exists $prop->{db_type} && $prop->{db_type} =~ /integer\[\]/) )) { $filter{$search_by} = int($search); } elsif ( ref $prop && $prop->{type} eq 'status' && $search =~ /\D/ ) { my $str; foreach my $pair ( @{$prop->{cases}} ) { if ( lc(Encode::decode('utf-8', $pair->[1])) eq lc(Encode::decode('utf-8', $search)) || lc(Encode::decode('utf-8', $pair->[0])) eq lc(Encode::decode('utf-8', $search)) ) { $str = $pair->[0]; last; } } if ( $str ) { $filter{$search_by} = $str; } } elsif ( ref $prop && ($prop->{type} eq 'pickup' || $prop->{type} eq 'lookup') && $search =~ /\D/ ) { my $lookup_opts = $prop->{lookup_opts}; if ( ref $lookup_opts && (exists $lookup_opts->{class} || exists $lookup_opts->{table}) ) { my $search_field = exists $lookup_opts->{search_by} ? $lookup_opts->{search_by} : 'name'; my @ids = $keeper->get_documents ( ids => 1, exists $lookup_opts->{class} ? (class => $lookup_opts->{class}) : (table => $lookup_opts->{table}), ilike => 1, $search_field => '%'.$search.'%', ); if ( @ids ) { $filter{$search_by} = \@ids; } else { $nothing_found = 1; } } } else { $filter{$search_by}='%'.$search.'%'; $filter{ilike} = 1; } } else { $filter{$search_by}='%'.$search.'%'; $filter{ilike} = 1; } } # Дополнительные фильтры раздела if ($section->filters) { no strict 'vars'; my $filters = eval($section->filters); if ($@) { warn "Bad filter: " . $section->filters . " in section " . $section->id; } elsif (ref $filters eq 'HASH') { while ( my ($key, $val) = each %$filters ) { $filter{$key} = $val; } } } my $n = ref $section && $section->_page_size ? $section->_page_size : 40; my $first = $n * ($p - 1); ($first,$p)=(0,0) if (!$section->no_count && $first>$total); $total = $keeper->get_documents( %filter, count => 1 ) unless $section->no_count; unless ( $nothing_found ) { if ( exists $params{class} && $params{class} && !(exists $params{use_section} && $params{use_section}) ) { @documents = $keeper->get_documents( %filter, %order, limit => $n, offset => $first ); } elsif ($sorted) { @documents = $keeper->get_sorted_documents( %filter ); } else { @documents = $keeper->get_documents( %filter, %order, limit => $n, offset => $first ); } } # набор колонок таблицы документов... my @columns = $sorted ? ({attr => '_sort_', name => 'N'}) : (); # пытаемся найти колонки, которые документ сам пожелал показать (required_properties -> column)... if ($filter{class} or @documents and $documents[0]) { push @columns, sort {$a->{column} <=> $b->{column}} grep {$_->{column}} ($filter{class} ? $filter{class}->new($keeper)->structure : $documents[0]->structure); } # стандартная жопка таблицы... @columns = (@columns, {attr => '_act_', rusname => 'Действия'}, ); my $toopi = $project->documents(); my $inline_status = 0; my $delete_status = 0; my %lookup_elements; my %document_classes; my @inline_pickups = grep { my $type = exists $_->{inline_type} ? $_->{inline_type} : $_->{type}; exists $_->{inline} && ($type eq 'pickup' || $type eq 'autocomplete') } @columns; map { $_->{document_access} = $user->section_accesses($user, $_->section); if ( $_->{document_access} == 2 ) { $delete_status = 1; } $document_classes{$_->class} = 1; } @documents; map { if ( exists $_->{inline} && $_->{inline} ) { $inline_status = 1; } } @columns; $result{success} = 1; $result{total} = $total; $result{page} = $p; $result{nothing_found} = $nothing_found; if ( $build_html ) { my $html = ''; foreach my $document ( @documents ) { next unless ref $document; $html .= $m->scomp( '/contenido/components/section_browse_row.msn', document => $document, columns => \@columns, section => $section, toopi => $toopi, inline_status => $inline_status, lookup_elemets => \%lookup_elements, filter => \%filter_params, params_unsection => $params_unsection, params_unclassed => $params_unclassed ); } $result{html} = Encode::decode('utf-8', $html); } if ( $return eq 'hash' ) { $result{inline_status} = $inline_status; $result{delete_status} = $delete_status; $result{columns} = \@columns; $result{documents} = \@documents; $result{lookup_elements} = \%lookup_elements; $result{filter} = \%filter_params; $result{toopi} = $toopi; $result{params_unsection} = $params_unsection; $result{params_unclassed} = $params_unclassed; } else { $result{columns} = scalar @columns; } } else { $result{error} = $return eq 'hash' ? 'Секция не найдена' : Encode::decode('utf-8', 'Секция не найдена'); } } else { $result{error} = $return eq 'hash' ? 'Переданы неверные параметры' : Encode::decode('utf-8', 'Переданы неверные параметры'); } my $json; if ( $return eq 'hash' ) { return %result; } else { $json = encode_json \%result; }