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

Last change on this file since 45 was 45, checked in by nanardon, 14 years ago
  • make all test pass
  • make search more accessible
File size: 8.7 KB
RevLine 
[5]1package Sophie::Controller::Search;
2use Moose;
3use namespace::autoclean;
[40]4use Sophie;
[5]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
[43]28    if ($c->req->param('page')) {
29        $c->req->params->{search} = $c->session->{search};
30    }
31
32    if ($c->req->param('search')) {
33        $c->session->{search} = $c->req->param('search');
[45]34        $c->forward('quick', [ undef, split(/\s/, $c->req->param('search')) ]);
[43]35        my $pager = $c->stash->{rs}->pager;
36        $c->stash->{pager} = $pager;
37        $c->stash->{xmlrpc} = [
38            $c->stash->{rs}->get_column('pkgid')->all
39        ];
40    }
[5]41}
42
[45]43sub adv :Local {
44    my ($self, $c) = @_;
45}
46
[43]47sub search_param : Private {
48    my ($self, $c) = @_;
49    my $r = {
50        rows => Sophie->config()->{'max_reply'} || 20000,
51        order_by => [ 'name', 'evr using >>', 'issrc' ],
52        select => [ 'pkgid' ],
53    };
54    if (!$c->req->xmlrpc->method) {
55        $r->{page} = $c->req->param('page') || 1;
[45]56        $r->{rows} = 20;
[43]57    }
58    return $r;
59}
60
[40]61sub distrib_search : Private {
62    my ( $self, $c, $searchspec ) = @_;
63
64    return $c->model('Base')->resultset('Distribution')
65        ->search(
66            {
67                $searchspec->{distribution}
68                    ? (name => $searchspec->{distribution})
69                    : ()
70            }
71        )->search_related('Release',
72            {
73                $searchspec->{release}
[43]74                    ? (version => $searchspec->{release})
[40]75                    : ()
76            }
77        )->search_related('Arch',
78            {
79                $searchspec->{arch}
80                    ? (arch => $searchspec->{arch})
81                    : ()
82            }
[45]83        )->search_related('Medias',
84            {
85                ($searchspec->{media} ? (label => $searchspec->{media}) : ()),
86                ($searchspec->{media_group}
87                    ? (group_label => $searchspec->{media_group}) 
88                    : ()),
89            }
90        )->search_related('MediasPaths')
[40]91        ->search_related('Paths')
92        ->search_related('Rpmfiles');
93}
94
[6]95sub bytag : XMLRPCPath('/search/rpm/bytag') {
96    my ( $self, $c, $searchspec, $tag, $tagvalue ) = @_;
[5]97
[40]98    my $tagrs = $c->model('Base')->resultset('Tags')
99        ->search({ tagname => lc($tag), value => $tagvalue})
100        ->get_column('pkgid');
101    $c->stash->{xmlrpc} = [ $c->model('Base')->resultset('Rpms')->search(
[6]102        {
[40]103            -and => [ 
104                (exists($searchspec->{src})
105                    ? { issrc => $searchspec->{src} ? 1 : 0 }
106                    : ()),
107                { pkgid => 
108                    { IN => $tagrs->as_query, },
109                },
110                { pkgid =>
111                    { IN => $c->forward('distrib_search', [ $searchspec
112                        ])->get_column('pkgid')->as_query, }, 
113                },
114            ]     
115        },
[43]116        $c->forward('search_param'),
[40]117    )->get_column('pkgid')->all ]
[6]118
119}
120
121sub bydep : XMLRPCPath('/search/rpm/bydep') {
122    my ( $self, $c, $searchspec, $deptype, $depname, $depsense, $depevr ) = @_;
123
[40]124    my $deprs = $c->model('Base')->resultset('Deps')->search(
[6]125        {
[40]126            deptype => $deptype,
127            depname => $depname,
128            ($depsense
129                ? (-nest => \[
130                    'rpmdepmatch(flags, evr, rpmsenseflag(?), ?)',
131                    [ plain_text => $depsense],
132                    [ plain_text => $depevr ]
133                ])
134            : ()),
[6]135        }
[40]136    )->get_column('pkgid');
137    $c->stash->{xmlrpc} = [ $c->model('Base')->resultset('Rpms')->search(
138        {
139            -and => [ 
140                (exists($searchspec->{src})
141                    ? { issrc => $searchspec->{src} ? 1 : 0 }
142                    : ()),
143                { pkgid => 
144                    { IN => $deprs->as_query, },
145                },
146                { pkgid =>
147                    { IN => $c->forward('distrib_search', [ $searchspec
148                        ])->get_column('pkgid')->as_query, }, 
149                },
150            ]     
151        },
[43]152        $c->forward('search_param'),
[40]153    )->get_column('pkgid')->all ]
[6]154}
155
[16]156sub byfile : XMLRPCPath('/search/rpm/byfile') {
157    my ( $self, $c, $searchspec, $file) = @_;
158    my ($dirname, $basename) = $file =~ m:^(.*/)?([^/]+)$:;
159
[40]160    my $filers = $c->model('Base')->resultset('Files')
161    ->search({
162            ($dirname
163                ? (dirname => $dirname)
164                : ()),
165            basename => $basename,
166        })
167    ->get_column('pkgid');
168    $c->stash->{xmlrpc} = [ $c->model('Base')->resultset('Rpms')->search(
[16]169        {
[40]170            -and => [ 
171                (exists($searchspec->{src})
172                    ? { issrc => $searchspec->{src} ? 1 : 0 }
173                    : ()),
174                { pkgid => 
175                    { IN => $filers->as_query, },
176                },
177                { pkgid =>
178                    { IN => $c->forward('distrib_search', [ $searchspec
179                        ])->get_column('pkgid')->as_query, }, 
180                },
181            ]     
182        },
[43]183        $c->forward('search_param'),
[40]184    )->get_column('pkgid')->all ]
[16]185}
186
[40]187sub fuzzy : XMLRPCPath('/search/rpm/fuzzy') {
188    my ($self, $c, $searchspec, $name) = @_;
189
190    my $deprs = $c->model('Base')->resultset('Deps')->search(
191        { deptype => 'P', depname => { '~*' => $name } }
192    )->get_column('pkgid');
193
[43]194    $c->stash->{rs} = 
195
196        $c->model('Base')->resultset('Rpms')->search(
[40]197        {
198            -and => [
199                (exists($searchspec->{src})
200                    ? { issrc => $searchspec->{src} ? 1 : 0 }
201                    : ()),
202                { -or => [
[44]203                    { name => 
204                        { '~*' => $name, },
[40]205                    },
206                    { pkgid =>
207                        { IN => $deprs->as_query, },
208                    }, ]
209                },
210                { pkgid =>
211                    { IN => $c->forward('distrib_search', [ $searchspec
212                        ])->get_column('pkgid')->as_query, }, 
213                },
214            ]     
215        },
[43]216        $c->forward('search_param'),
217    );
218   
219    if ($c->req->xmlrpc->method) {
220        $c->stash->{xmlrpc} = [ 
221            $c->stash->{rs}->get_column('pkgid')->all
222        ];
223    }
[40]224}
225
[45]226sub quick : XMLRPCPath('/search/rpm/quick') {
227    my ($self, $c, $searchspec, @keywords) = @_;
228    my $tsquery = join(' & ', map { $_ =~ s/ /\\ /g; $_ } @keywords);
229    $c->stash->{rs} = $c->model('Base')->resultset('Rpms')->search(
230            {
231                -or => [
232                    { -nest => \[
233                        "to_tsvector('english', description) @@ to_tsquery(?)",
234                        [ plain_text => $tsquery],
235                    ], },
236                    {
237                    name => [ @keywords ],
238                    },
239                ],
240            (exists($searchspec->{src})
241                ? (issrc => $searchspec->{src} ? 1 : 0)
242                : ()),
243            pkgid =>
244            { IN => $c->forward('distrib_search', [ $searchspec
245                    ])->get_column('pkgid')->as_query, }, 
246
247
248        },
249        {
250            %{$c->forward('search_param')},
251        },
252    );
253    if ($c->req->xmlrpc->method) {
254        $c->stash->{xmlrpc} = [ 
255            $c->stash->{rs}->get_column('pkgid')->all
256        ];
257    }
258}
259
[40]260sub description : XMLRPCPath('/search/rpm/description') {
261    my ($self, $c, $searchspec, @keywords) = @_;
262    my $tsquery = join(' & ', map { $_ =~ s/ /\\ /g; $_ } @keywords);
[45]263    $c->stash->{rs} = $c->model('Base')->resultset('Rpms')->search(
[40]264        {
265            -nest => \[
266                    "to_tsvector('english', description) @@ to_tsquery(?)",
267                    [ plain_text => $tsquery],
268                ],
269                (exists($searchspec->{src})
270                    ? (issrc => $searchspec->{src} ? 1 : 0)
271                    : ()),
272                pkgid =>
273                    { IN => $c->forward('distrib_search', [ $searchspec
274                ])->get_column('pkgid')->as_query, }, 
275               
276         
277        },
278        {
[43]279            %{$c->forward('search_param')},
[40]280            select => [ 
281                "ts_rank_cd(to_tsvector('english', description),to_tsquery(?)) as rank",
282                'pkgid'
283            ],
284            bind => [ $tsquery ], 
285            order_by => [ 'rank desc', 'name', 'evr using >>', 'issrc' ],
286        },
[45]287    );
288    if ($c->req->xmlrpc->method) {
289        $c->stash->{xmlrpc} = [ 
290            $c->stash->{rs}->get_column('pkgid')->all
291        ];
292    }
[40]293}
294
[5]295=head1 AUTHOR
296
297Olivier Thauvin
298
299=head1 LICENSE
300
301This library is free software. You can redistribute it and/or modify
302it under the same terms as Perl itself.
303
304=cut
305
306__PACKAGE__->meta->make_immutable;
307
3081;
Note: See TracBrowser for help on using the repository browser.