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
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    }
31
32    if ($c->req->param('search')) {
33        $c->session->{search} = $c->req->param('search');
34        $c->forward('quick', [ undef, split(/\s/, $c->req->param('search')) ]);
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    }
41}
42
43sub adv :Local {
44    my ($self, $c) = @_;
45}
46
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;
56        $r->{rows} = 20;
57    }
58    return $r;
59}
60
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}
74                    ? (version => $searchspec->{release})
75                    : ()
76            }
77        )->search_related('Arch',
78            {
79                $searchspec->{arch}
80                    ? (arch => $searchspec->{arch})
81                    : ()
82            }
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')
91        ->search_related('Paths')
92        ->search_related('Rpmfiles');
93}
94
95sub bytag : XMLRPCPath('/search/rpm/bytag') {
96    my ( $self, $c, $searchspec, $tag, $tagvalue ) = @_;
97
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(
102        {
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        },
116        $c->forward('search_param'),
117    )->get_column('pkgid')->all ]
118
119}
120
121sub bydep : XMLRPCPath('/search/rpm/bydep') {
122    my ( $self, $c, $searchspec, $deptype, $depname, $depsense, $depevr ) = @_;
123
124    my $deprs = $c->model('Base')->resultset('Deps')->search(
125        {
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            : ()),
135        }
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        },
152        $c->forward('search_param'),
153    )->get_column('pkgid')->all ]
154}
155
156sub byfile : XMLRPCPath('/search/rpm/byfile') {
157    my ( $self, $c, $searchspec, $file) = @_;
158    my ($dirname, $basename) = $file =~ m:^(.*/)?([^/]+)$:;
159
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(
169        {
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        },
183        $c->forward('search_param'),
184    )->get_column('pkgid')->all ]
185}
186
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
194    $c->stash->{rs} = 
195
196        $c->model('Base')->resultset('Rpms')->search(
197        {
198            -and => [
199                (exists($searchspec->{src})
200                    ? { issrc => $searchspec->{src} ? 1 : 0 }
201                    : ()),
202                { -or => [
203                    { name => 
204                        { '~*' => $name, },
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        },
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    }
224}
225
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
260sub description : XMLRPCPath('/search/rpm/description') {
261    my ($self, $c, $searchspec, @keywords) = @_;
262    my $tsquery = join(' & ', map { $_ =~ s/ /\\ /g; $_ } @keywords);
263    $c->stash->{rs} = $c->model('Base')->resultset('Rpms')->search(
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        {
279            %{$c->forward('search_param')},
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        },
287    );
288    if ($c->req->xmlrpc->method) {
289        $c->stash->{xmlrpc} = [ 
290            $c->stash->{rs}->get_column('pkgid')->all
291        ];
292    }
293}
294
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.