diff options
author | mkanat%bugzilla.org <> | 2006-11-04 08:16:46 +0100 |
---|---|---|
committer | mkanat%bugzilla.org <> | 2006-11-04 08:16:46 +0100 |
commit | 7f94705675428a544f82d485f79f60f052e67fdf (patch) | |
tree | fce95d9d62f4db3d7a267b4c0d6c0d5ab43b3567 /Bugzilla | |
parent | 9162305edb319289526f4503f5839bb21ea82724 (diff) | |
download | bugzilla-7f94705675428a544f82d485f79f60f052e67fdf.tar.gz bugzilla-7f94705675428a544f82d485f79f60f052e67fdf.tar.xz |
Bug 352403: Create an object for saved searches, and have Bugzilla::User use it
Patch By Max Kanat-Alexander <mkanat@bugzilla.org> r=LpSolit, a=myk
Diffstat (limited to 'Bugzilla')
-rw-r--r-- | Bugzilla/Group.pm | 27 | ||||
-rw-r--r-- | Bugzilla/Search/Saved.pm | 186 | ||||
-rw-r--r-- | Bugzilla/User.pm | 164 |
3 files changed, 299 insertions, 78 deletions
diff --git a/Bugzilla/Group.pm b/Bugzilla/Group.pm index 0f7771efe..c80d2333c 100644 --- a/Bugzilla/Group.pm +++ b/Bugzilla/Group.pm @@ -81,6 +81,20 @@ sub _rederive_regexp { RederiveRegexp($self->user_regexp, $self->id); } +sub members_non_inherited { + my ($self) = @_; + return $self->{members_non_inherited} + if exists $self->{members_non_inherited}; + + my $member_ids = Bugzilla->dbh->selectcol_arrayref( + 'SELECT DISTINCT user_id FROM user_group_map + WHERE isbless = 0 AND group_id = ?', + undef, $self->id) || []; + require Bugzilla::User; + $self->{members_non_inherited} = Bugzilla::User->new_from_list($member_ids); + return $self->{members_non_inherited}; +} + ################################ ##### Module Subroutines ### ################################ @@ -246,3 +260,16 @@ be a member of this group. and undef otherwise. =back + +=head1 METHODS + +=over + +=item C<members_non_inherited> + +Returns an arrayref of L<Bugzilla::User> objects representing people who are +"directly" in this group, meaning that they're in it because they match +the group regular expression, or they have been actually added to the +group manually. + +=back diff --git a/Bugzilla/Search/Saved.pm b/Bugzilla/Search/Saved.pm new file mode 100644 index 000000000..2cb53439d --- /dev/null +++ b/Bugzilla/Search/Saved.pm @@ -0,0 +1,186 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# The Initial Developer of the Original Code is Everything Solved. +# Portions created by Everything Solved are Copyright (C) 2006 +# Everything Solved. All Rights Reserved. +# +# Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org> + +use strict; + +package Bugzilla::Search::Saved; + +use base qw(Bugzilla::Object); + +use Bugzilla::CGI; +use Bugzilla::Constants; +use Bugzilla::Group; +use Bugzilla::Search qw(IsValidQueryType); +use Bugzilla::User; + +############# +# Constants # +############# + +use constant DB_TABLE => 'namedqueries'; + +use constant DB_COLUMNS => qw( + id + userid + name + query + query_type +); + +##################### +# Complex Accessors # +##################### + +sub edit_link { + my ($self) = @_; + return $self->{edit_link} if defined $self->{edit_link}; + my $cgi = new Bugzilla::CGI($self->url); + if (!$cgi->param('query_type') + || !IsValidQueryType($cgi->param('query_type'))) + { + $cgi->param('query_type', 'advanced'); + } + $self->{edit_link} = $cgi->canonicalise_query; + return $self->{edit_link}; +} + +sub used_in_whine { + my ($self) = @_; + return $self->{used_in_whine} if exists $self->{used_in_whine}; + ($self->{used_in_whine}) = Bugzilla->dbh->selectrow_array( + 'SELECT 1 FROM whine_events INNER JOIN whine_queries + ON whine_events.id = whine_queries.eventid + WHERE whine_events.owner_userid = ? AND query_name = ?', undef, + $self->{userid}, $self->name) || 0; + return $self->{used_in_whine}; +} + +sub link_in_footer { + my ($self, $user) = @_; + # We only cache link_in_footer for the current Bugzilla->user. + return $self->{link_in_footer} if exists $self->{link_in_footer} && !$user; + my $user_id = $user ? $user->id : Bugzilla->user->id; + my $link_in_footer = Bugzilla->dbh->selectrow_array( + 'SELECT 1 FROM namedqueries_link_in_footer + WHERE namedquery_id = ? AND user_id = ?', + undef, $self->id, $user_id) || 0; + $self->{link_in_footer} = $link_in_footer if !$user; + return $link_in_footer; +} + +sub shared_with_group { + my ($self) = @_; + return $self->{shared_with_group} if exists $self->{shared_with_group}; + # Bugzilla only currently supports sharing with one group, even + # though the database backend allows for an infinite number. + my ($group_id) = Bugzilla->dbh->selectrow_array( + 'SELECT group_id FROM namedquery_group_map WHERE namedquery_id = ?', + undef, $self->id); + $self->{shared_with_group} = $group_id ? new Bugzilla::Group($group_id) + : undef; + return $self->{shared_with_group}; +} + +#################### +# Simple Accessors # +#################### + +sub bug_ids_only { return ($_[0]->{'query_type'} == LIST_OF_BUGS) ? 1 : 0; } +sub url { return $_[0]->{'query'}; } + +sub user { + my ($self) = @_; + return $self->{user} if defined $self->{user}; + $self->{user} = new Bugzilla::User($self->{userid}); + return $self->{user}; +} + +1; + +__END__ + +=head1 NAME + + Bugzilla::Search::Saved - A saved search + +=head1 SYNOPSIS + + use Bugzilla::Search::Saved; + + my $query = new Bugzilla::Search::Saved($query_id); + + my $edit_link = $query->edit_link; + my $search_url = $query->url; + my $owner = $query->user; + +=head1 DESCRIPTION + +This module exists to represent a L<Bugzilla::Search> that has been +saved to the database. + +This is an implementation of L<Bugzilla::Object>, and so has all the +same methods available as L<Bugzilla::Object>, in addition to what is +documented below. + +=head1 METHODS + +=head2 Constructors and Database Manipulation + +=over + +=item C<new> + +Does not accept a bare C<name> argument. Instead, accepts only an id. + +See also: L<Bugzilla::Object/new>. + +=back + + +=head2 Accessors + +These return data about the object, without modifying the object. + +=over + +=item C<edit_link> + +A url with which you can edit the search. + +=item C<url> + +The CGI parameters for the search, as a string. + +=item C<link_in_footer> + +Whether or not this search should be displayed in the footer for the +I<current user> (not the owner of the search, but the person actually +using Bugzilla right now). + +=item C<bug_ids_only> + +True if the search contains only a list of Bug IDs. + +=item C<shared_with_group> + +The L<Bugzilla::Group> that this search is shared with. C<undef> if +this search isn't shared. + +=back diff --git a/Bugzilla/User.pm b/Bugzilla/User.pm index 28c79254c..cadc8574d 100644 --- a/Bugzilla/User.pm +++ b/Bugzilla/User.pm @@ -272,56 +272,61 @@ sub nick { sub queries { my $self = shift; - return $self->{queries} if defined $self->{queries}; return [] unless $self->id; my $dbh = Bugzilla->dbh; - my $used_in_whine_ref = $dbh->selectall_hashref(' - SELECT DISTINCT query_name - FROM whine_events we - INNER JOIN whine_queries wq - ON we.id = wq.eventid - WHERE we.owner_userid = ?', - 'query_name', undef, $self->id); - - # If the user is in any group, there may be shared queries to be included. - my $or_nqgm_group_id_in_usergroups = ''; - if ($self->groups_as_string) { - $or_nqgm_group_id_in_usergroups = - 'OR MAX(nqgm.group_id) IN (' . $self->groups_as_string . ') '; - } + my $query_ids = $dbh->selectcol_arrayref( + 'SELECT id FROM namedqueries WHERE userid = ?', undef, $self->id); + require Bugzilla::Search::Saved; + $self->{queries} = Bugzilla::Search::Saved->new_from_list($query_ids); + return $self->{queries}; +} - my $queries_ref = $dbh->selectall_arrayref(' - SELECT nq.id, MAX(userid) AS userid, name, query, query_type, - MAX(nqgm.group_id) AS shared_with_group, - COUNT(nql.namedquery_id) AS link_in_footer - FROM namedqueries AS nq - LEFT JOIN namedquery_group_map nqgm - ON nqgm.namedquery_id = nq.id - LEFT JOIN namedqueries_link_in_footer AS nql - ON nql.namedquery_id = nq.id - AND nql.user_id = ? ' . - $dbh->sql_group_by('nq.id', 'name, query, query_type') . - ' HAVING MAX(nq.userid) = ? ' . - $or_nqgm_group_id_in_usergroups . - ' ORDER BY UPPER(name)', - {'Slice'=>{}}, $self->id, $self->id); - - foreach my $queries_hash (@$queries_ref) { - # For each query, determine whether it's being used in a whine. - if (exists($$used_in_whine_ref{$queries_hash->{'name'}})) { - $queries_hash->{'usedinwhine'} = 1; - } +sub queries_subscribed { + my $self = shift; + return $self->{queries_subscribed} if defined $self->{queries_subscribed}; + return [] unless $self->id; - # For shared queries, provide the sharer's user object. - if ($queries_hash->{'userid'} != $self->id) { - $queries_hash->{'user'} = new Bugzilla::User($queries_hash->{'userid'}); - } - } - $self->{queries} = $queries_ref; + # Exclude the user's own queries. + my @my_query_ids = map($_->id, @{$self->queries}); + my $query_id_string = join(',', @my_query_ids) || '-1'; + + # Only show subscriptions that we can still actually see. If a + # user changes the shared group of a query, our subscription + # will remain but we won't have access to the query anymore. + my $subscribed_query_ids = Bugzilla->dbh->selectcol_arrayref( + "SELECT lif.namedquery_id + FROM namedqueries_link_in_footer lif + INNER JOIN namedquery_group_map ngm + ON ngm.namedquery_id = lif.namedquery_id + WHERE lif.user_id = ? + AND lif.namedquery_id NOT IN ($query_id_string) + AND ngm.group_id IN (" . $self->groups_as_string . ")", + undef, $self->id); + require Bugzilla::Search::Saved; + $self->{queries_subscribed} = + Bugzilla::Search::Saved->new_from_list($subscribed_query_ids); + return $self->{queries_subscribed}; +} - return $self->{queries}; +sub queries_available { + my $self = shift; + return $self->{queries_available} if defined $self->{queries_available}; + return [] unless $self->id; + + # Exclude the user's own queries. + my @my_query_ids = map($_->id, @{$self->queries}); + my $query_id_string = join(',', @my_query_ids) || '-1'; + + my $avail_query_ids = Bugzilla->dbh->selectcol_arrayref( + 'SELECT namedquery_id FROM namedquery_group_map + WHERE group_id IN (' . $self->groups_as_string . ") + AND namedquery_id NOT IN ($query_id_string)"); + require Bugzilla::Search::Saved; + $self->{queries_available} = + Bugzilla::Search::Saved->new_from_list($avail_query_ids); + return $self->{queries_available}; } sub settings { @@ -345,6 +350,8 @@ sub flush_queries_cache { my $self = shift; delete $self->{queries}; + delete $self->{queries_subscribed}; + delete $self->{queries_available}; } sub groups { @@ -1663,6 +1670,42 @@ confirmation screen. =head1 METHODS +=head2 Saved and Shared Queries + +=over + +=item C<queries> + +Returns an arrayref of the user's own saved queries, sorted by name. The +array contains L<Bugzilla::Search::Saved> objects. + +=item C<queries_subscribed> + +Returns an arrayref of shared queries that the user has subscribed to. +That is, these are shared queries that the user sees in their footer. +This array contains L<Bugzilla::Search::Saved> objects. + +=item C<queries_available> + +Returns an arrayref of all queries to which the user could possibly +subscribe. This includes the contents of L</queries_subscribed>. +An array of L<Bugzilla::Search::Saved> objects. + +=item C<flush_queries_cache> + +Some code modifies the set of stored queries. Because C<Bugzilla::User> does +not handle these modifications, but does cache the result of calling C<queries> +internally, such code must call this method to flush the cached result. + +=item C<queryshare_groups> + +An arrayref of group ids. The user can share their own queries with these +groups. + +=back + +=head2 Other Methods + =over =item C<id> @@ -1711,35 +1754,6 @@ returned. Sets the L<Bugzilla::Auth> object to be returned by C<authorizer()>. Should only be called by C<Bugzilla::Auth::login>, for the most part. -=item C<queries> - -Returns an array of the user's named queries, sorted in a case-insensitive -order by name. Each entry is a hash with five keys: - -=over - -=item * - -id - The ID of the query - -=item * - -userid - The query owner's user ID - -=item * - -name - The name of the query - -=item * - -query - The text for the query - -=item * - -link_in_footer - Whether or not the query should be displayed in the footer. - -=back - =item C<disabledtext> Returns the disable text of the user, if any. @@ -1758,12 +1772,6 @@ value - the value of this setting for this user. Will be the same is_default - a boolean to indicate whether the user has chosen to make a preference for themself or use the site default. -=item C<flush_queries_cache> - -Some code modifies the set of stored queries. Because C<Bugzilla::User> does -not handle these modifications, but does cache the result of calling C<queries> -internally, such code must call this method to flush the cached result. - =item C<groups> Returns a hashref of group names for groups the user is a member of. The keys |