package Sophie::Controller::Search; use Moose; use namespace::autoclean; use Sophie; BEGIN {extends 'Catalyst::Controller'; } =head1 NAME Sophie::Controller::Search - Catalyst Controller =head1 DESCRIPTION Catalyst Controller. =head1 METHODS =cut =head2 index =cut sub index :Path :Args(0) { my ($self, $c) = @_; if ($c->req->param('page')) { $c->req->params->{search} = $c->session->{search}; $c->req->params->{type} = $c->session->{type}; $c->req->params->{deptype} = $c->session->{deptype}; foreach (qw(distribution release arch)) { $c->req->params->{$_} = $c->session->{search_dist}{$_}; } } else { $c->session->{search} = $c->req->params->{search}; $c->session->{type} = $c->req->params->{type}; $c->session->{deptype} = $c->req->params->{deptype}; foreach (qw(distribution release arch)) { $c->session->{search_dist}{$_} = $c->req->params->{$_}; } } my $searchspec = { %{ $c->session->{search_dist} } }; for ($c->req->param('type')) { /^fuzzyname$/ and do { $c->stash->{sargs} = [ {}, $c->req->param('search') ]; $c->visit('/search/rpm/fuzzy_rpc', [ $searchspec, $c->req->param('search') || undef ]); last; }; /^byname$/ and do { $c->stash->{sargs} = [ {}, $c->req->param('search') ]; $c->visit('/search/rpm/byname_rpc', [ $searchspec, $c->req->param('search') || undef ]); last; }; /^bydep$/ and do { my @args = ($c->req->param('deptype'), grep { $_ } split(/\s+/, $c->req->param('search') || '' )); $c->stash->{sargs} = [ {}, @args ], $c->visit('/search/rpm/bydep_rpc', [ $searchspec, @args ]); last; }; /^byfile$/ and do { my @args = ($c->req->param('search') || ''); $c->stash->{sargs} = [ {}, @args ], $c->visit('/search/rpm/byfile_rpc', [ $searchspec, @args ]); last; }; } #$c->forward('/search/rpm/end'); } sub results :Local { my ( $self, $c ) = @_; if ($c->req->param('page')) { $c->req->params->{search} ||= $c->session->{search}; } if ($c->req->param('search')) { $c->session->{search} = $c->req->param('search'); $c->visit('/search/rpm/quick', [ { src => 0, } , grep { $_ } split(/\s/, $c->req->param('search')) ]); } $c->forward('/search/rpm/end'); } sub adv_search :Local { my ( $self, $c ) = @_; } sub distrib_search : Private { my ( $self, $c, $searchspec, $asfilter ) = @_; # if asfilter is set, return undef if nothing would have been filter if (my $rs = $c->forward('/distrib/distrib_rs', [ $searchspec, $asfilter ])) { return $rs ->search_related('MediasPaths') ->search_related('Paths') ->search_related('Rpmfiles'); } else { return; } } sub byname_rs : Private { my ( $self, $c, $searchspec, $name, $sense, $evr ) = @_; $searchspec ||= {}; my $distrs = $c->forward('distrib_search', [ $searchspec, 1 ]); return $c->model('Base::Rpms')->search( { -and => [ (exists($searchspec->{src}) ? { issrc => $searchspec->{src} ? 1 : 0 } : ()), { name => $name }, ( $evr ? { -nest => \[ "rpmdepmatch(rpmsenseflag('='), evr, rpmsenseflag(?), ?)", [ plain_text => $sense], [ plain_text => $evr ], ] } : ()), ($distrs ? { pkgid => { IN => $distrs->get_column('pkgid')->as_query, }, } : ()), ] }, { order_by => [ 'name', 'evr using >>', 'issrc' ], } ); } sub bytag_rs : Private { my ( $self, $c, $searchspec, $tag, $tagvalue ) = @_; $searchspec ||= {}; my $tagrs = $c->model('Base')->resultset('Tags') ->search({ tagname => lc($tag), value => $tagvalue}) ->get_column('pkgid'); my $distrs = $c->forward('distrib_search', [ $searchspec, 1 ]); return $c->model('Base')->resultset('Rpms')->search( { -and => [ (exists($searchspec->{src}) ? { issrc => $searchspec->{src} ? 1 : 0 } : ()), { pkgid => { IN => $tagrs->as_query, }, }, $distrs ? { pkgid => { IN => $distrs->get_column('pkgid')->as_query, }, } : (), ] }, ); } sub bypkgid_rs : Private { my ( $self, $c, $searchspec, $pkgid ) = @_; $searchspec ||= {}; my $distrs = $c->forward('distrib_search', [ $searchspec, 1 ]); return $c->model('Base::Rpms')->search( { -and => [ (exists($searchspec->{src}) ? { issrc => $searchspec->{src} ? 1 : 0 } : ()), { pkgid => $pkgid }, $distrs ? { pkgid => { IN => $distrs->get_column('pkgid')->as_query, } } : () ] }, ); } sub deps_rs : Private { my ($self, $c, $searchspec, $deptype, $depname, $depsense, $depevr ) = @_; my $distrs = $c->forward('distrib_search', [ $searchspec, 1 ]); return $c->model('Base::Deps')->search( { -and => [ { deptype => $deptype }, { depname => $depname }, ($depsense ? ({-nest => \[ 'rpmdepmatch(flags, evr, rpmsenseflag(?), ?)', [ plain_text => $depsense], [ plain_text => $depevr ] ]}) : ()), ($distrs ? ({ pkgid => { IN => $distrs->get_column('pkgid')->as_query, },}) : ()), (exists($searchspec->{src}) ? { pkgid => { IN => $c->model('Base::Rpms')->search( { issrc => $searchspec->{src} ? 1 : 0 } )->get_column('pkgid')->as_query, }, } : ()), ($searchspec->{pkgid} ? { pkgid => $searchspec->{pkgid} } : ()), ] }, { '+select' => [ { rpmsenseflag => 'flags' }, 'depname', ], '+as' => [ qw(sense name) ], } ); } sub file_rs : Private { my ( $self, $c, $searchspec, $file) = @_; my ($dirname, $basename) = $file =~ m:^(.*/)?([^/]+)$:; $dirname =~ m:^[/]: or $dirname = undef; if (!$dirname) { if ($file =~ /(\*|\?)/) { $file =~ tr/*?/%_/; } else { $file = '%' . $file; } } $searchspec ||= {}; my $distrs = $c->forward('distrib_search', [ $searchspec, 1 ]); return $c->model('Base::Files')->search( { -and => [ ($dirname ? (dirname => $dirname) : ()), { 'dirname || basename' => { LIKE => $file } }, basename => $basename, ($searchspec->{content} ? { has_content => 1 } : ()), ($distrs ? (pkgid => { IN => $distrs->get_column('pkgid')->as_query, },) : ()), ($searchspec->{pkgid} ? { pkgid => { IN => $searchspec->{pkgid} } } : ()), ], }, { '+select' => [ 'contents is NOT NULL as has_content', { rpmfilesmode => 'mode' }, ], '+as' => [ qw(has_content perm), ], } ); } sub end : Private { my ($self, $c, $searchspec) = @_; if ($c->action =~ m:search/[^/]+/.:) { my $rs = $c->stash->{rs}->search( {}, { page => $searchspec->{page} || $c->req->param('page') || 1, rows => $searchspec->{rows} || $c->req->param('rows') || 10, }, ); $c->stash->{rs} = $rs; my @results = map { { $_->get_columns } } $rs->all; $c->stash->{xmlrpc} = {}; if (!$searchspec->{nopager}) { my $pager = $c->stash->{rs}->pager; $c->stash->{pager} = $pager; $c->stash->{xmlrpc} = { pages => $pager->last_page, current_page => $pager->current_page, total_entries => $pager->total_entries, entries_per_page => $pager->entries_per_page, }; } $c->stash->{xmlrpc}{results} = \@results; } else { $c->forward('/end'); } } =head1 AUTHOR Olivier Thauvin =head1 LICENSE This library is free software. You can redistribute it and/or modify it under the same terms as Perl itself. =cut __PACKAGE__->meta->make_immutable; 1;