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

Last change on this file since 83 was 83, checked in by nanardon, 14 years ago
  • fix doc
File size: 11.8 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
29sub results :Local {
30    my ( $self, $c ) = @_;
31
32    if ($c->req->param('page')) {
33        $c->req->params->{search} ||= $c->session->{search};
34    }
35
36    if ($c->req->param('search')) {
37        $c->session->{search} = $c->req->param('search');
38        $c->forward('quick', [ undef, grep { $_ } split(/\s/, $c->req->param('search')) ]);
39        my $pager = $c->stash->{rs}->pager;
40        $c->stash->{pager} = $pager;
41        $c->stash->{xmlrpc} = {
42            results => [ $c->stash->{rs}->get_column('pkgid')->all ],
43            pages => $pager->last_page,
44            current_page => $pager->current_page,
45            total_entries => $pager->total_entries,
46            entries_per_page => $pager->entries_per_page,
47        };
48    }
49}
50
51sub search_param : Private {
52    my ($self, $c) = @_;
53    my $r = {
54        rows => Sophie->config()->{'max_reply'} || 20000,
55        order_by => [ 'name', 'evr using >>', 'issrc' ],
56        select => [ 'pkgid' ],
57    };
58    if (!$c->req->xmlrpc->method) {
59        $r->{page} = $c->req->param('page') || 1;
60        $r->{rows} = $c->req->param('rows') || 15;
61    }
62    return $r;
63}
64
65sub distrib_search : Private {
66    my ( $self, $c, $searchspec ) = @_;
67
68    return $c->forward('/distrib/distrib_rs', [ $searchspec ])
69        ->search_related('MediasPaths')
70        ->search_related('Paths')
71        ->search_related('Rpmfiles');
72}
73
74sub format_search : Private {
75    my ( $self, $c, $searchspec ) = @_;
76
77    my $rs = $c->stash->{rs}->search(
78        {},
79        {
80            page => $searchspec->{page} || 1,
81            rows => $searchspec->{rows} || 10,
82        },
83    );
84
85    if (!$searchspec->{page}) {
86        my $pager = $rs->pager;
87        $c->stash->{xmlrpc} = {
88                pages => $pager->last_page,
89                current_page => $pager->current_page,
90                total_entries => $pager->total_entries,
91                entries_per_page => $pager->entries_per_page,
92        };
93    }
94    $c->stash->{xmlrpc}{results} = [ $rs->get_column('pkgid')->all ];
95    return $c->stash->{xmlrpc};
96}
97
98sub bypkgid : XMLRPCPath('/search/rpm/bypkgid') {
99    my ( $self, $c, $searchspec, $pkgid ) = @_;
100
101    $c->stash->{rs} = $c->model('Base')->resultset('Rpms')->search(
102        {
103            -and => [ 
104                (exists($searchspec->{src})
105                    ? { issrc => $searchspec->{src} ? 1 : 0 }
106                    : ()),
107                { pkgid => $pkgid }, 
108                { pkgid =>
109                    { IN => $c->forward('distrib_search', [ $searchspec
110                        ])->get_column('pkgid')->as_query, }, 
111                },
112            ]     
113        },
114    );
115
116    $c->forward('format_search', $searchspec);
117}
118
119sub bytag : XMLRPCPath('/search/rpm/bytag') {
120    my ( $self, $c, $searchspec, $tag, $tagvalue ) = @_;
121
122    my $tagrs = $c->model('Base')->resultset('Tags')
123        ->search({ tagname => lc($tag), value => $tagvalue})
124        ->get_column('pkgid');
125    $c->stash->{rs} = $c->model('Base')->resultset('Rpms')->search(
126        {
127            -and => [ 
128                (exists($searchspec->{src})
129                    ? { issrc => $searchspec->{src} ? 1 : 0 }
130                    : ()),
131                { pkgid => 
132                    { IN => $tagrs->as_query, },
133                },
134                { pkgid =>
135                    { IN => $c->forward('distrib_search', [ $searchspec
136                        ])->get_column('pkgid')->as_query, }, 
137                },
138            ]     
139        },
140    );
141    $c->forward('format_search', $searchspec);
142
143}
144
145sub bydep : XMLRPCPath('/search/rpm/bydep') {
146    my ( $self, $c, $searchspec, $deptype, $depname, $depsense, $depevr ) = @_;
147
148    my $deprs = $c->model('Base')->resultset('Deps')->search(
149        {
150            deptype => $deptype,
151            depname => $depname,
152            ($depsense
153                ? (-nest => \[
154                    'rpmdepmatch(flags, evr, rpmsenseflag(?), ?)',
155                    [ plain_text => $depsense],
156                    [ plain_text => $depevr ]
157                ])
158            : ()),
159        }
160    )->get_column('pkgid');
161    $c->stash->{rs} = $c->model('Base')->resultset('Rpms')->search(
162        {
163            -and => [ 
164                (exists($searchspec->{src})
165                    ? { issrc => $searchspec->{src} ? 1 : 0 }
166                    : ()),
167                { pkgid => 
168                    { IN => $deprs->as_query, },
169                },
170                { pkgid =>
171                    { IN => $c->forward('distrib_search', [ $searchspec
172                        ])->get_column('pkgid')->as_query, }, 
173                },
174            ]     
175        },
176    );
177    $c->forward('format_search', $searchspec);
178}
179
180sub byfile : XMLRPCPath('/search/rpm/byfile') {
181    my ( $self, $c, $searchspec, $file) = @_;
182    my ($dirname, $basename) = $file =~ m:^(.*/)?([^/]+)$:;
183
184    my $filers = $c->model('Base')->resultset('Files')
185    ->search({
186            ($dirname
187                ? (dirname => $dirname)
188                : ()),
189            basename => $basename,
190        })
191    ->get_column('pkgid');
192    $c->stash->{rs} = $c->model('Base')->resultset('Rpms')->search(
193        {
194            -and => [ 
195                (exists($searchspec->{src})
196                    ? { issrc => $searchspec->{src} ? 1 : 0 }
197                    : ()),
198                { pkgid => 
199                    { IN => $filers->as_query, },
200                },
201                { pkgid =>
202                    { IN => $c->forward('distrib_search', [ $searchspec
203                        ])->get_column('pkgid')->as_query, }, 
204                },
205            ]     
206        },
207    );
208    $c->forward('format_search', $searchspec);
209}
210
211sub fuzzy : XMLRPCPath('/search/rpm/fuzzy') {
212    my ($self, $c, $searchspec, $name) = @_;
213
214    my $deprs = $c->model('Base')->resultset('Deps')->search(
215        { deptype => 'P', depname => { '~*' => $name } }
216    )->get_column('pkgid');
217
218    $c->stash->{rs} = 
219
220        $c->model('Base')->resultset('Rpms')->search(
221        {
222            -and => [
223                (exists($searchspec->{src})
224                    ? { issrc => $searchspec->{src} ? 1 : 0 }
225                    : ()),
226                { -or => [
227                    { name => 
228                        { '~*' => $name, },
229                    },
230#                    { pkgid =>
231#                        { IN => $deprs->as_query, },
232#                    },
233                     ]
234                },
235                { pkgid =>
236                    { IN => $c->forward('distrib_search', [ $searchspec
237                        ])->get_column('pkgid')->as_query, }, 
238                },
239            ]     
240        },
241        $c->forward('search_param'),
242    );
243   
244    $c->forward('format_search', $searchspec);
245}
246
247sub quick : XMLRPCPath('/search/rpm/quick') {
248    my ($self, $c, $searchspec, @keywords) = @_;
249    my $tsquery = join(' & ', map { $_ =~ s/ /\\ /g; $_ } @keywords);
250    $c->stash->{rs} = $c->model('Base')->resultset('Rpms')->search(
251            {
252                -or => [
253                    { -nest => \[
254                        "to_tsvector('english', description) @@ to_tsquery(?)",
255                        [ plain_text => $tsquery],
256                    ], },
257                    {
258                    name => [ @keywords ],
259                    },
260                ],
261            (exists($searchspec->{src})
262                ? (issrc => $searchspec->{src} ? 1 : 0)
263                : ()),
264            pkgid =>
265            { IN => $c->forward('distrib_search', [ $searchspec
266                    ])->get_column('pkgid')->as_query, }, 
267
268
269        },
270        {
271            %{$c->forward('search_param')},
272        },
273    );
274    $c->forward('format_search', $searchspec);
275}
276
277sub description : XMLRPCPath('/search/rpm/description') {
278    my ($self, $c, $searchspec, @keywords) = @_;
279    my $tsquery = join(' & ', map { $_ =~ s/ /\\ /g; $_ } @keywords);
280    $c->stash->{rs} = $c->model('Base')->resultset('Rpms')->search(
281        {
282            -nest => \[
283                    "to_tsvector('english', description) @@ to_tsquery(?)",
284                    [ plain_text => $tsquery],
285                ],
286                (exists($searchspec->{src})
287                    ? (issrc => $searchspec->{src} ? 1 : 0)
288                    : ()),
289                pkgid =>
290                    { IN => $c->forward('distrib_search', [ $searchspec
291                ])->get_column('pkgid')->as_query, }, 
292               
293         
294        },
295        {
296            %{$c->forward('search_param')},
297            select => [ 
298                "ts_rank_cd(to_tsvector('english', description),to_tsquery(?)) as rank",
299                'pkgid'
300            ],
301            bind => [ $tsquery ], 
302            order_by => [ 'rank desc', 'name', 'evr using >>', 'issrc' ],
303        },
304    );
305    $c->forward('format_search', $searchspec);
306}
307
308=head2 search.rpms.bydate (SEARCHSPEC, TIMESTAMP)
309
310Return a list of rpms files added since TIMESTAMP.
311TIMESTAMP must the number of second since 1970-01-01 (eq UNIX epoch).
312
313SEARCHSPEC is a struct with following key/value:
314
315=over 4
316
317=item distribution
318
319Limit search to this distribution
320
321=item release
322
323Limit search to this release
324
325=item arch
326
327Limit search to distribution of this arch
328
329=item src
330
331If set to true, limit search to source package, If set to false, limit search to
332binary package.
333
334=item name
335
336Limit search to rpm having this name
337
338=item rows
339
340Set maximum of results, the default is 10000.
341
342=back
343
344Each elements of the output is a struct:
345
346=over 4
347
348=item filename
349
350the rpm filename
351
352=item pkgid
353
354the identifier of the package
355
356=item distribution
357
358the distribution containing this package
359
360=item release
361
362the release containing this package
363
364=item arch
365
366the arch containing this package
367
368=item media
369
370the media containing this package
371
372=back
373
374=cut
375
376sub bydate : XMLRPCPath('/search/rpms/bydate') {
377    my ( $self, $c, $searchspec, $date ) = @_;
378
379    return $c->stash->{xmlrpc} = [
380        map {
381            { 
382                filename => $_->get_column('filename'),
383                pkgid    => $_->get_column('pkgid'), 
384                distribution => $_->get_column('name'),
385                release => $_->get_column('version'),
386                arch => $_->get_column('arch'),
387                media => $_->get_column('label'),
388            }
389        }
390        $c->forward('/distrib/distrib_rs', [ $searchspec ])
391        ->search_related('MediasPaths')
392        ->search_related('Paths')
393        ->search_related('Rpmfiles',
394            {
395                -nest => \[
396                    "Rpmfiles.added > '1970-01-01'::date + ?::interval",
397                    [ plain_text => "$date seconds" ],   
398                ],
399                pkgid => {
400                    IN => $c->model('Base::Rpms')->search(
401                        {
402                            (exists($searchspec->{name})
403                                ? (name => $searchspec->{name})
404                                : ()
405                            ),
406                            (exists($searchspec->{src})
407                                ? (issrc => $searchspec->{src} ? 1 : 0)
408                                : ()
409                            ),
410                        }
411                    )->get_column('pkgid')->as_query,
412                }
413            },
414            {
415                select => [qw(filename pkgid name version arch label) ],
416                rows => $searchspec->{rows} || 10000,
417                order_by => [ 'Rpmfiles.added desc' ],
418            },
419        )->all ];
420}
421
422=head1 AUTHOR
423
424Olivier Thauvin
425
426=head1 LICENSE
427
428This library is free software. You can redistribute it and/or modify
429it under the same terms as Perl itself.
430
431=cut
432
433__PACKAGE__->meta->make_immutable;
434
4351;
Note: See TracBrowser for help on using the repository browser.