Line # Revision Author
1 621 ahitrov <% $json %>
2 <%once>
3
4 use JSON::XS;
5
6 </%once>
7 <%args>
8
9 $id => undef
10 $params => undef
11 $return => 'json'
12 $section => undef
13 $build_html => 1
14
15 </%args>
16 <%init>
17
18 my %result;
19
20 if ( ($return eq 'json' && $id && $id =~ /^\d+$/) || ($return eq 'hash' && ref $section) ) {
21 $section = $keeper->get_section_by_id( $id ) unless ref $section;
22 if ( ref $section ) {
23 my %params;
24 if ( ref $params eq 'HASH' ) {
25 %params = %$params;
26 } elsif ( ref $params eq 'ARRAY' ) {
27 map {
28 if ( ref $_ eq 'ARRAY' && scalar @$_ == 2 ) {
29 $params{$_->[0]} = $_->[1];
30 } elsif ( $_ =~ /(.+?)=(.*)/ ) {
31 $params{$1} = $2
32 }
33 } @$params;
34 } elsif ( $params ) {
35 map { if ( $_ =~ /(.+?)=(.*)/ ) { $params{$1} = $2 } } split(/\&/, $params);
36 }
37 my $params_unclassed = join ('&', map { $_.'='.$params{$_} } grep { $_ ne 'class' } keys %params );
38 my $params_unsection = join ('&', map { $_.'='.$params{$_} } grep { $_ ne 's' } keys %params );
39
40 my %filter_params;
41 $filter_params{use_section} = $params{use_section} if exists $params{use_section} && $params{use_section};
42 $filter_params{class} = $params{class} if exists $params{class} && $params{class};
43 $filter_params{alpha} = $params{alpha} if exists $params{alpha} && $params{alpha};
44 $filter_params{alpha_search} = $params{alpha_search} if exists $params{alpha_search} && $params{alpha_search};
45 $filter_params{search_by} = $params{search_by} if exists $params{search_by} && $params{search_by};
46 $filter_params{search} = $params{search} if exists $params{search} && $params{search};
47 $filter_params{p} = $params{p} if exists $params{p} && $params{p} > 1;
48 $filter_params{s} = $params{id} if exists $params{id} && $params{id};
49 my $p = exists $params{p} && $params{p} ? $params{p} : 1;
50
51 # Фильтры работают в любом случае...
52 my $filter = $m->comp('/contenido/components/context.msn', name => 'filter');
53 my $profile = $m->comp('/contenido/components/context.msn', name => 'profile');
54
55 unless (defined $request->{section_accesses}->{$id}) {
56 $request->{section_accesses}->{$id} = $user->get_section_access($id);
57 }
58 my $section_access = $request->{section_accesses}->{$id};
59
60 my (@documents, $total);
61 my $s = $section->id;
62 my $sorted = $section->_sorted();
63 $s .= ",$filter" if ($filter > 0);
64
65 my %filter;
66 my $nothing_found = 0;
67 my %order = (!(exists $params{class} && $params{class}) && $section->order_by) ? (order_by => $section->order_by) : (order => ['date','direct']);
68 if ( exists $params{alpha} and $params{alpha} ne '' ) {
69 $filter{ilike} = 1;
70 $filter{ $params{alpha_search} || 'name' } = $params{alpha}."%";
71 $order{order} = ['name','reverse'];
72 delete $order{order_by};
73 }
74
75 if ( exists $params{class} && $params{class} ) {
76 $filter{class} = $params{class};
77 } elsif ( $section->default_document_class ) {
78 $filter{class} = $section->default_document_class;
79 } elsif ( $section->default_table_class ) {
80 $filter{table} = $section->default_table_class;
81 }
82 $filter{s} = $s unless exists $params{class} && $params{class} && !(exists $params{use_section} && $params{use_section});
83
84 if ( exists $params{search_by} && $params{search_by} && exists $params{search} && defined $params{search} ) {
85 my $doc_class = exists $params{class} && $params{class} ? $params{class} : $section->default_document_class;
86 my $search = $params{search};
87 my $search_by = $params{search_by};
88 if ( $doc_class ) {
89 my @props = $doc_class->new( $keeper )->structure();
90 my ($prop) = grep { $_->{attr} eq $search_by } @props if @props;
91 if ( ref $prop && ($prop->{type} eq 'integer' || $prop->{type} eq 'checkbox' ||
92 (($prop->{type} eq 'pickup' || $prop->{type} eq 'lookup' || $prop->{type} eq 'status') && $search =~ /^\d+$/) ||
93 (exists $prop->{db_type} && $prop->{db_type} =~ /integer\[\]/) )) {
94 $filter{$search_by} = int($search);
95 } elsif ( ref $prop && $prop->{type} eq 'status' && $search =~ /\D/ ) {
96 my $str;
97 foreach my $pair ( @{$prop->{cases}} ) {
98 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)) ) {
99 $str = $pair->[0];
100 last;
101 }
102 }
103 if ( $str ) {
104 $filter{$search_by} = $str;
105 }
106 } elsif ( ref $prop && ($prop->{type} eq 'pickup' || $prop->{type} eq 'lookup') && $search =~ /\D/ ) {
107 my $lookup_opts = $prop->{lookup_opts};
108 if ( ref $lookup_opts && (exists $lookup_opts->{class} || exists $lookup_opts->{table}) ) {
109 my $search_field = exists $lookup_opts->{search_by} ? $lookup_opts->{search_by} : 'name';
110 my @ids = $keeper->get_documents (
111 ids => 1,
112 exists $lookup_opts->{class} ? (class => $lookup_opts->{class}) : (table => $lookup_opts->{table}),
113 ilike => 1,
114 $search_field => '%'.$search.'%',
115 );
116 if ( @ids ) {
117 $filter{$search_by} = \@ids;
118 } else {
119 $nothing_found = 1;
120 }
121 }
122 } else {
123 $filter{$search_by}='%'.$search.'%';
124 $filter{ilike} = 1;
125 }
126 } else {
127 $filter{$search_by}='%'.$search.'%';
128 $filter{ilike} = 1;
129 }
130 }
131
132 # Дополнительные фильтры раздела
133 if ($section->filters) {
134 no strict 'vars';
135 my $filters = eval($section->filters);
136 if ($@) {
137 warn "Bad filter: " . $section->filters . " in section " . $section->id;
138 } elsif (ref $filters eq 'HASH') {
139 while ( my ($key, $val) = each %$filters ) {
140 $filter{$key} = $val;
141 }
142 }
143 }
144
145 my $n = ref $section && $section->_page_size ? $section->_page_size : 40;
146 my $first = $n * ($p - 1);
147 ($first,$p)=(0,0) if (!$section->no_count && $first>$total);
148
149 $total = $keeper->get_documents( %filter, count => 1 ) unless $section->no_count;
150 unless ( $nothing_found ) {
151 if ( exists $params{class} && $params{class} && !(exists $params{use_section} && $params{use_section}) ) {
152 @documents = $keeper->get_documents( %filter, %order, limit => $n, offset => $first );
153 } elsif ($sorted) {
154 @documents = $keeper->get_sorted_documents( %filter );
155 } else {
156 @documents = $keeper->get_documents( %filter, %order, limit => $n, offset => $first );
157 }
158 }
159
160 # набор колонок таблицы документов...
161 my @columns = $sorted ? ({attr => '_sort_', name => 'N'}) : ();
162
163 # пытаемся найти колонки, которые документ сам пожелал показать (required_properties -> column)...
164 if ($filter{class} or @documents and $documents[0]) {
165 push @columns,
166 sort {$a->{column} <=> $b->{column}}
167 grep {$_->{column}} ($filter{class} ? $filter{class}->new($keeper)->structure : $documents[0]->structure);
168 }
169
170 # стандартная жопка таблицы...
171 @columns = (@columns,
172 {attr => '_act_', rusname => 'Действия'},
173 );
174
175 my $toopi = $project->documents();
176 my $inline_status = 0;
177 my $delete_status = 0;
178
179 my %lookup_elements;
180 my %document_classes;
181 my @inline_pickups = grep {
182 my $type = exists $_->{inline_type} ? $_->{inline_type} : $_->{type};
183 exists $_->{inline} && ($type eq 'pickup' || $type eq 'autocomplete')
184 } @columns;
185
186 map {
187 $_->{document_access} = $user->section_accesses($user, $_->section);
188 if ( $_->{document_access} == 2 ) {
189 $delete_status = 1;
190 }
191 $document_classes{$_->class} = 1;
192 } @documents;
193 map {
194 if ( exists $_->{inline} && $_->{inline} ) {
195 $inline_status = 1;
196 }
197 } @columns;
198
199 $result{success} = 1;
200 $result{total} = $total;
201 $result{page} = $p;
202 $result{nothing_found} = $nothing_found;
203 if ( $build_html ) {
204 my $html = '';
205 foreach my $document ( @documents ) {
206 next unless ref $document;
207 $html .= $m->scomp( '/contenido/components/section_browse_row.msn',
208 document => $document,
209 columns => \@columns,
210 section => $section,
211 toopi => $toopi,
212 inline_status => $inline_status,
213 lookup_elemets => \%lookup_elements,
214 filter => \%filter_params,
215 params_unsection => $params_unsection,
216 params_unclassed => $params_unclassed
217 );
218 }
219 $result{html} = Encode::decode('utf-8', $html);
220 }
221 if ( $return eq 'hash' ) {
222 $result{inline_status} = $inline_status;
223 $result{delete_status} = $delete_status;
224 $result{columns} = \@columns;
225 $result{documents} = \@documents;
226 $result{lookup_elements} = \%lookup_elements;
227 $result{filter} = \%filter_params;
228 $result{toopi} = $toopi;
229 $result{params_unsection} = $params_unsection;
230 $result{params_unclassed} = $params_unclassed;
231 } else {
232 $result{columns} = scalar @columns;
233 }
234 } else {
235 $result{error} = $return eq 'hash' ? 'Секция не найдена' : Encode::decode('utf-8', 'Секция не найдена');
236 }
237 } else {
238 $result{error} = $return eq 'hash' ? 'Переданы неверные параметры' : Encode::decode('utf-8', 'Переданы неверные параметры');
239 }
240
241 my $json;
242 if ( $return eq 'hash' ) {
243 return %result;
244 } else {
245 $json = encode_json \%result;
246 }
247
248 </%init>

Небольшая справка по веткам

cnddist – контейнер, в котором хранятся все дистрибутивы всех библиотек и программных пакетов, которые использовались при построении различных версий Contenido. Если какой-то библиотеки в данном хранилище нет, инсталлятор сделает попытку "подтянуть" ее с веба (например, с CPAN). Если библиотека слишком старая, есть очень большая вероятность, что ее там уже нет. Поэтому мы храним весь хлам от всех сборок. Если какой-то дистрибутив вдруг отсутствует в cnddist - напишите нам, мы положим его туда.

koi8 – отмирающая ветка, чей код, выдача и все внутренние библиотеки заточены на кодировку KOI8-R. Вносятся только те дополнения, которые касаются внешнего вида и функционала админки, баги ядра, обязательные обновления портов и мелочи, которые легко скопипастить. В дальнейшем планируется полная остановка поддержки по данной ветке.

utf8 – актуальная ветка, заточенная под UTF-8.

Внутри каждой ветки: core – исходники ядра; install – скрипт установки инсталляции; plugins – плагины; samples – "готовые к употреблению" проекты, которые можно поставить, запустить и посмотреть, как они работают.