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

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