source: server/trunk/web/lib/Sophie/Controller/Search.pm @ 327

Last change on this file since 327 was 327, checked in by nanardon, 13 years ago
  • add 'fuzzy search' type search
File size: 9.1 KB
Line 
1package Sophie::Controller::Search;
2use Moose;
3use namespace::autoclean;
4use Sophie;
5
6BEGIN {extends 'Catalyst::Controller'; }
7
8=head1 NAME
9
10Sophie::Controller::Search - Catalyst Controller
11
12=head1 DESCRIPTION
13
14Catalyst Controller.
15
16=head1 METHODS
17
18=cut
19
20
21=head2 index
22
23=cut
24
25sub index :Path :Args(0) {
26    my ($self, $c) = @_;
27
28    if ($c->req->param('page')) {
29        $c->req->params->{search} = $c->session->{search};
30        $c->req->params->{type} = $c->session->{type};
31        $c->req->params->{deptype} = $c->session->{deptype};
32        foreach (qw(distribution release arch)) {
33            $c->req->params->{$_} = $c->session->{search_dist}{$_};
34        }
35    } else {
36        $c->session->{search} = $c->req->params->{search};
37        $c->session->{type} = $c->req->params->{type};
38        $c->session->{deptype} = $c->req->params->{deptype};
39        foreach (qw(distribution release arch)) {
40            $c->session->{search_dist}{$_} = $c->req->params->{$_};
41        }
42    }
43
44    my $searchspec = { %{ $c->session->{search_dist} } };
45
46    for ($c->req->param('type')) {
47        /^fuzzyname$/ and do {
48            $c->stash->{sargs} = [ {}, $c->req->param('search') ];
49            $c->visit('/search/rpm/fuzzy_rpc', [ $searchspec, $c->req->param('search') ||
50                    undef ]);
51            last;
52        };
53        /^byname$/ and do {
54            $c->stash->{sargs} = [ {}, $c->req->param('search') ];
55            $c->visit('/search/rpm/byname_rpc', [ $searchspec, $c->req->param('search') ||
56                    undef ]);
57            last;
58        };
59        /^bydep$/ and do {
60            my @args = ($c->req->param('deptype'), grep { $_ }
61                split(/\s+/, $c->req->param('search') || '' ));
62            $c->stash->{sargs} = [ {}, @args ],
63            $c->visit('/search/rpm/bydep_rpc', [ $searchspec, @args ]);
64            last;
65        };
66        /^byfile$/ and do {
67            my @args = ($c->req->param('search') || '');
68            $c->stash->{sargs} = [ {}, @args ],
69            $c->visit('/search/rpm/byfile_rpc', [ $searchspec, @args ]);
70            last;
71        };
72    }
73    #$c->forward('/search/rpm/end');
74}
75
76sub results :Local {
77    my ( $self, $c ) = @_;
78
79    if ($c->req->param('page')) {
80        $c->req->params->{search} ||= $c->session->{search};
81    }
82
83    if ($c->req->param('search')) {
84        $c->session->{search} = $c->req->param('search');
85        $c->visit('/search/rpm/quick', [
86                {
87                    src => 0,
88                } , grep { $_ } split(/\s/, $c->req->param('search')) ]);
89
90    }
91    $c->forward('/search/rpm/end');
92}
93
94sub adv_search :Local {
95    my ( $self, $c ) = @_;
96}
97
98sub distrib_search : Private {
99    my ( $self, $c, $searchspec, $asfilter ) = @_;
100
101    # if asfilter is set, return undef if nothing would have been filter
102    if (my $rs = $c->forward('/distrib/distrib_rs', [ $searchspec, $asfilter ]))
103    {
104        return $rs
105            ->search_related('MediasPaths')
106            ->search_related('Paths')
107            ->search_related('Rpmfiles');
108        } else {
109            return;
110        }
111}
112
113sub byname_rs : Private {
114    my ( $self, $c, $searchspec, $name, $sense, $evr ) = @_;
115    $searchspec ||= {};
116
117    my $distrs = $c->forward('distrib_search', [ $searchspec, 1 ]);
118
119    return $c->model('Base::Rpms')->search(
120        {
121            -and => [ 
122                (exists($searchspec->{src})
123                    ? { issrc => $searchspec->{src} ? 1 : 0 }
124                    : ()),
125                { name => $name },
126                ( $evr
127                    ? { -nest => \[ 
128                        "rpmdepmatch(rpmsenseflag('='), evr, rpmsenseflag(?), ?)",
129                        [ plain_text => $sense],
130                        [ plain_text => $evr ],
131                    ] }
132                    : ()),
133                ($distrs
134                    ? { pkgid => { IN => $distrs->get_column('pkgid')->as_query, }, }
135                    : ()),
136            ]     
137        },
138        {
139                order_by => [ 'name', 'evr using >>', 'issrc' ],
140        }
141    );
142}
143
144sub bytag_rs : Private {
145    my ( $self, $c, $searchspec, $tag, $tagvalue ) = @_;
146    $searchspec ||= {};
147
148    my $tagrs = $c->model('Base')->resultset('Tags')
149        ->search({ tagname => lc($tag), value => $tagvalue})
150        ->get_column('pkgid');
151    my $distrs = $c->forward('distrib_search', [ $searchspec, 1 ]);
152    return $c->model('Base')->resultset('Rpms')->search(
153        {
154            -and => [ 
155                (exists($searchspec->{src})
156                    ? { issrc => $searchspec->{src} ? 1 : 0 }
157                    : ()),
158                { pkgid => 
159                    { IN => $tagrs->as_query, },
160                },
161                $distrs
162                    ? { pkgid => { IN => $distrs->get_column('pkgid')->as_query, }, }
163                    : (),
164            ]     
165        },
166    );
167}
168
169sub bypkgid_rs : Private {
170    my ( $self, $c, $searchspec, $pkgid ) = @_;
171    $searchspec ||= {};
172
173    my $distrs = $c->forward('distrib_search', [ $searchspec, 1 ]);
174
175    return $c->model('Base::Rpms')->search(
176        {
177            -and => [ 
178                (exists($searchspec->{src})
179                    ? { issrc => $searchspec->{src} ? 1 : 0 }
180                    : ()),
181                { pkgid => $pkgid },
182                $distrs
183                    ? { pkgid => { IN => $distrs->get_column('pkgid')->as_query, } }
184                    : ()
185            ]     
186        },
187    );
188}
189
190sub deps_rs : Private {
191    my ($self, $c, $searchspec, $deptype, $depname, $depsense, $depevr ) = @_;
192
193    my $distrs = $c->forward('distrib_search', [ $searchspec, 1 ]);
194
195    return $c->model('Base::Deps')->search(
196        {
197            -and => [
198            { deptype => $deptype },
199            { depname => $depname },
200            ($depsense
201                ? ({-nest => \[
202                    'rpmdepmatch(flags, evr, rpmsenseflag(?), ?)',
203                    [ plain_text => $depsense],
204                    [ plain_text => $depevr ]
205                ]})
206            : ()),
207            ($distrs 
208                ? ({ pkgid => { IN => $distrs->get_column('pkgid')->as_query,
209                        },})
210                : ()),
211            (exists($searchspec->{src})
212                ? { pkgid => { IN => $c->model('Base::Rpms')->search(
213                            { issrc => $searchspec->{src} ? 1 : 0 }
214                        )->get_column('pkgid')->as_query, }, }
215                : ()),
216            ($searchspec->{pkgid}
217                ? { pkgid => $searchspec->{pkgid} }
218                : ()),
219            ]
220        },
221        {
222            '+select' => [ { rpmsenseflag => 'flags' }, 'depname', ],
223            '+as'     => [ qw(sense name) ],
224
225        }
226    );
227}
228
229sub file_rs : Private {
230    my ( $self, $c, $searchspec, $file) = @_;
231    my ($dirname, $basename) = $file =~ m:^(.*/)?([^/]+)$:;
232    $dirname =~ m:^[/]: or $dirname = undef;
233    if (!$dirname) {
234        if ($file =~ /(\*|\?)/) {
235            $file =~ tr/*?/%_/;
236        } else {
237            $file = '%' . $file;
238        }
239    }
240    $searchspec ||= {};
241
242    my $distrs = $c->forward('distrib_search', [ $searchspec, 1 ]);
243
244    return $c->model('Base::Files')->search(
245        {
246            -and => [
247                ($dirname
248                    ? (dirname => $dirname)
249                    : ()),
250                { 'dirname || basename' => { LIKE => $file } },
251                basename => $basename,
252                ($searchspec->{content} ? { has_content => 1 } : ()),
253                ($distrs 
254                    ? (pkgid => { IN => $distrs->get_column('pkgid')->as_query, },)
255                    : ()),
256                ($searchspec->{pkgid}
257                    ? { pkgid => { IN => $searchspec->{pkgid} } }
258                    : ()),
259            ],
260        },
261        {
262            '+select' => [
263                'contents is NOT NULL as has_content',
264                { rpmfilesmode => 'mode' },
265            ],
266            '+as' => [ qw(has_content perm), ],
267        }
268    );
269}
270
271sub end : Private {
272    my ($self, $c, $searchspec) = @_;
273
274    if ($c->action =~ m:search/[^/]+/.:) {
275        my $rs = $c->stash->{rs}->search(
276            {},
277            {
278                page => $searchspec->{page} || 
279                     $c->req->param('page') || 1,
280                rows => $searchspec->{rows} || 
281                     $c->req->param('rows') || 10,
282            },
283        );
284
285        $c->stash->{rs} = $rs;
286        my @results = map { { $_->get_columns } } $rs->all;
287
288        $c->stash->{xmlrpc} = {};
289        if (!$searchspec->{nopager}) {
290            my $pager = $c->stash->{rs}->pager;
291            $c->stash->{pager} = $pager;
292            $c->stash->{xmlrpc} = {
293                    pages => $pager->last_page,
294                    current_page => $pager->current_page,
295                    total_entries => $pager->total_entries,
296                    entries_per_page => $pager->entries_per_page,
297            };
298        }
299        $c->stash->{xmlrpc}{results} = \@results;
300    } else {
301        $c->forward('/end');
302    }
303}
304
305=head1 AUTHOR
306
307Olivier Thauvin
308
309=head1 LICENSE
310
311This library is free software. You can redistribute it and/or modify
312it under the same terms as Perl itself.
313
314=cut
315
316__PACKAGE__->meta->make_immutable;
317
3181;
Note: See TracBrowser for help on using the repository browser.