From 95052864ee662a67639a3080b3ecf7a1e24ba9e3 Mon Sep 17 00:00:00 2001 From: Dave Lawrence Date: Thu, 24 May 2012 12:57:14 -0400 Subject: Bug 747193 - Add search field to product chooser to allow selecting product/component based on keyword search r=glob --- extensions/BMO/lib/WebService.pm | 67 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'extensions/BMO/lib') diff --git a/extensions/BMO/lib/WebService.pm b/extensions/BMO/lib/WebService.pm index 95bdcbdf3..cd3b9a92c 100644 --- a/extensions/BMO/lib/WebService.pm +++ b/extensions/BMO/lib/WebService.pm @@ -26,6 +26,7 @@ use base qw(Bugzilla::WebService); use Bugzilla::Constants; use Bugzilla::Error; +use Bugzilla::Util qw(detaint_natural trick_taint); use Bugzilla::WebService::Util qw(validate); use Bugzilla::Field; @@ -99,6 +100,72 @@ sub getBugsVerifier { return \%users; } +sub prod_comp_search { + my ($self, $params) = @_; + my $user = Bugzilla->user; + my $dbh = Bugzilla->switch_to_shadow_db(); + + my $search = $params->{'search'}; + $search || ThrowCodeError('param_required', + { function => 'Bug.prod_comp_search', param => 'search' }); + + my $limit = detaint_natural($params->{'limit'}) + ? $dbh->sql_limit($params->{'limit'}) + : ''; + + # We do this in the DB directly as we want it to be fast and + # not have the overhead of loading full product objects + + # All products which the user has "Entry" access to. + my $enterable_ids = $dbh->selectcol_arrayref( + 'SELECT products.id FROM products + LEFT JOIN group_control_map + ON group_control_map.product_id = products.id + AND group_control_map.entry != 0 + AND group_id NOT IN (' . $user->groups_as_string . ') + WHERE group_id IS NULL + AND products.isactive = 1'); + + if (scalar @$enterable_ids) { + # And all of these products must have at least one component + # and one version. + $enterable_ids = $dbh->selectcol_arrayref( + 'SELECT DISTINCT products.id FROM products + WHERE ' . $dbh->sql_in('products.id', $enterable_ids) . + ' AND products.id IN (SELECT DISTINCT components.product_id + FROM components + WHERE components.isactive = 1) + AND products.id IN (SELECT DISTINCT versions.product_id + FROM versions + WHERE versions.isactive = 1)'); + } + + return { products => [] } if !scalar @$enterable_ids; + + my @list; + foreach my $word (split(/[\s,]+/, $search)) { + if ($word ne "") { + my $sql_word = $dbh->quote($word); + trick_taint($sql_word); + # XXX CONCAT_WS is MySQL specific + my $field = "CONCAT_WS(' ', products.name, components.name, components.description)"; + push(@list, $dbh->sql_iposition($sql_word, $field) . " > 0"); + } + } + + my $products = $dbh->selectall_arrayref(" + SELECT products.name AS product, + components.name AS component + FROM products + INNER JOIN components ON products.id = components.product_id + WHERE (" . join(" AND ", @list) . ") + AND products.id IN (" . join(",", @$enterable_ids) . ") + ORDER BY products.name $limit", + { Slice => {} }); + + return { products => $products }; +} + 1; __END__ -- cgit v1.2.3-24-g4f1b