Bugzilla::Group: code style

hinted-selects
Vitaliy Filippov 2014-10-10 15:48:38 +04:00
parent 7d40840dd1
commit 9a7e557879
2 changed files with 168 additions and 154 deletions

View File

@ -66,7 +66,8 @@ use constant UPDATE_VALIDATORS => {
# Database Manipulation #
#########################
sub update {
sub update
{
my $self = shift;
my $changes = $self->SUPER::update(@_);
$self->bug->_sync_fulltext();

View File

@ -1,5 +1,3 @@
# -*- 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
@ -28,7 +26,10 @@ package Bugzilla::Group;
use base qw(Bugzilla::Object);
use Bugzilla::Bug;
use Bugzilla::Constants;
use Bugzilla::Product;
use Bugzilla::User;
use Bugzilla::Util;
use Bugzilla::Error;
use Bugzilla::Config qw(:admin);
@ -55,8 +56,8 @@ use constant VALIDATORS => {
name => \&_check_name,
description => \&_check_description,
userregexp => \&_check_user_regexp,
isactive => \&_check_is_active,
isbuggroup => \&_check_is_bug_group,
isactive => \&Bugzilla::Object::check_boolean,
isbuggroup => \&Bugzilla::Object::check_boolean,
icon_url => \&_check_icon_url,
};
@ -71,52 +72,55 @@ use constant UPDATE_COLUMNS => qw(
);
# Parameters that are lists of groups.
use constant GROUP_PARAMS => qw(chartgroup insidergroup timetrackinggroup
querysharegroup);
use constant GROUP_PARAMS => qw(chartgroup insidergroup timetrackinggroup querysharegroup);
###############################
#### Accessors ######
###############################
sub description { return $_[0]->{'description'}; }
sub is_bug_group { return $_[0]->{'isbuggroup'}; }
sub user_regexp { return $_[0]->{'userregexp'}; }
sub is_active { return $_[0]->{'isactive'}; }
sub icon_url { return $_[0]->{'icon_url'}; }
sub description { return $_[0]->{description}; }
sub is_bug_group { return $_[0]->{isbuggroup}; }
sub user_regexp { return $_[0]->{userregexp}; }
sub is_active { return $_[0]->{isactive}; }
sub icon_url { return $_[0]->{icon_url}; }
sub bugs {
sub bugs
{
my $self = shift;
return $self->{bugs} if exists $self->{bugs};
my $bug_ids = Bugzilla->dbh->selectcol_arrayref(
'SELECT bug_id FROM bug_group_map WHERE group_id = ?',
undef, $self->id);
require Bugzilla::Bug;
undef, $self->id
);
$self->{bugs} = Bugzilla::Bug->new_from_list($bug_ids);
return $self->{bugs};
}
sub members_direct {
sub members_direct
{
my ($self) = @_;
$self->{members_direct} ||= $self->_get_members(GRANT_DIRECT);
return $self->{members_direct};
}
sub members_non_inherited {
sub members_non_inherited
{
my ($self) = @_;
$self->{members_non_inherited} ||= $self->_get_members();
return $self->{members_non_inherited};
}
# A helper for members_direct and members_non_inherited
sub _get_members {
sub _get_members
{
my ($self, $grant_type) = @_;
my $dbh = Bugzilla->dbh;
my $grant_clause = $grant_type ? "AND grant_type = $grant_type" : "";
my $user_ids = $dbh->selectcol_arrayref(
"SELECT DISTINCT user_id
FROM user_group_map
WHERE isbless = 0 $grant_clause AND group_id = ?", undef, $self->id);
require Bugzilla::User;
"SELECT DISTINCT user_id FROM user_group_map".
" WHERE isbless = 0 $grant_clause AND group_id = ?",
undef, $self->id
);
return Bugzilla::User->new_from_list($user_ids);
}
@ -203,64 +207,71 @@ sub users_in_group
return $users;
}
sub flag_types {
sub flag_types
{
my $self = shift;
require Bugzilla::FlagType;
$self->{flag_types} ||= Bugzilla::FlagType::match({ group => $self->id });
return $self->{flag_types};
}
sub grant_direct {
sub grant_direct
{
my ($self, $type) = @_;
$self->{grant_direct} ||= {};
return $self->{grant_direct}->{$type}
if defined $self->{grant_direct}->{$type};
return $self->{grant_direct}->{$type} if defined $self->{grant_direct}->{$type};
my $dbh = Bugzilla->dbh;
my $ids = $dbh->selectcol_arrayref(
"SELECT member_id FROM group_group_map
WHERE grantor_id = ? AND grant_type = $type",
undef, $self->id) || [];
"SELECT member_id FROM group_group_map".
" WHERE grantor_id = ? AND grant_type = $type",
undef, $self->id
) || [];
$self->{grant_direct}->{$type} = $self->new_from_list($ids);
return $self->{grant_direct}->{$type};
}
sub granted_by_direct {
sub granted_by_direct
{
my ($self, $type) = @_;
$self->{granted_by_direct} ||= {};
return $self->{granted_by_direct}->{$type}
if defined $self->{granted_by_direct}->{$type};
return $self->{granted_by_direct}->{$type} if defined $self->{granted_by_direct}->{$type};
my $dbh = Bugzilla->dbh;
my $ids = $dbh->selectcol_arrayref(
"SELECT grantor_id FROM group_group_map
WHERE member_id = ? AND grant_type = $type",
undef, $self->id) || [];
"SELECT grantor_id FROM group_group_map".
" WHERE member_id = ? AND grant_type = $type",
undef, $self->id
) || [];
$self->{granted_by_direct}->{$type} = $self->new_from_list($ids);
return $self->{granted_by_direct}->{$type};
}
sub products {
sub products
{
my $self = shift;
return $self->{products} if exists $self->{products};
my $product_data = Bugzilla->dbh->selectall_arrayref(
'SELECT product_id, entry, membercontrol, othercontrol,
canedit, editcomponents, editbugs, canconfirm
FROM group_control_map WHERE group_id = ?', {Slice=>{}},
$self->id);
'SELECT product_id, entry, membercontrol, othercontrol,'.
' canedit, editcomponents, editbugs, canconfirm'.
' FROM group_control_map WHERE group_id = ?',
{Slice=>{}}, $self->id
);
my @ids = map { $_->{product_id} } @$product_data;
require Bugzilla::Product;
my $products = Bugzilla::Product->new_from_list(\@ids);
my $products = Bugzilla::Product->new_from_list(\@ids);
my %data_map = map { $_->{product_id} => $_ } @$product_data;
my @retval;
foreach my $product (@$products) {
foreach my $product (@$products)
{
# Data doesn't need to contain product_id--we already have
# the product object.
delete $data_map{$product->id}->{product_id};
push(@retval, { controls => $data_map{$product->id},
product => $product });
push @retval, {
controls => $data_map{$product->id},
product => $product
};
}
$self->{products} = \@retval;
return $self->{products};
@ -276,17 +287,21 @@ sub set_name { $_[0]->set('name', $_[1]); }
sub set_user_regexp { $_[0]->set('userregexp', $_[1]); }
sub set_icon_url { $_[0]->set('icon_url', $_[1]); }
sub update {
sub update
{
my $self = shift;
my $dbh = Bugzilla->dbh;
$dbh->bz_start_transaction();
my $changes = $self->SUPER::update(@_);
if (exists $changes->{name}) {
if (exists $changes->{name})
{
my ($old_name, $new_name) = @{$changes->{name}};
my $update_params;
foreach my $group (GROUP_PARAMS) {
if ($old_name eq Bugzilla->params->{$group}) {
foreach my $group (GROUP_PARAMS)
{
if ($old_name eq Bugzilla->params->{$group})
{
SetParam($group, $new_name);
$update_params = 1;
}
@ -295,154 +310,147 @@ sub update {
}
# If we've changed this group to be active, fix any Mandatory groups.
$self->_enforce_mandatory if (exists $changes->{isactive}
&& $changes->{isactive}->[1]);
$self->_enforce_mandatory if exists $changes->{isactive} && $changes->{isactive}->[1];
$self->_rederive_regexp() if exists $changes->{userregexp};
Bugzilla::Hook::process('group_end_of_update',
{ group => $self, changes => $changes });
Bugzilla::Hook::process('group_end_of_update', { group => $self, changes => $changes });
$dbh->bz_commit_transaction();
return $changes;
}
sub check_remove {
sub check_remove
{
my ($self, $params) = @_;
# System groups cannot be deleted!
if (!$self->is_bug_group) {
if (!$self->is_bug_group)
{
ThrowUserError("system_group_not_deletable", { name => $self->name });
}
# Groups having a special role cannot be deleted.
my @special_groups;
foreach my $special_group (GROUP_PARAMS) {
if ($self->name eq Bugzilla->params->{$special_group}) {
push(@special_groups, $special_group);
foreach my $special_group (GROUP_PARAMS)
{
if ($self->name eq Bugzilla->params->{$special_group})
{
push @special_groups, $special_group;
}
}
if (scalar(@special_groups)) {
ThrowUserError('group_has_special_role',
{ name => $self->name,
groups => \@special_groups });
if (@special_groups)
{
ThrowUserError('group_has_special_role', {
name => $self->name,
groups => \@special_groups,
});
}
return if $params->{'test_only'};
return if $params->{test_only};
my $cantdelete = 0;
my $users = $self->members_non_inherited;
if (scalar(@$users) && !$params->{'remove_from_users'}) {
$cantdelete = 1;
}
my $bugs = $self->bugs;
if (scalar(@$bugs) && !$params->{'remove_from_bugs'}) {
$cantdelete = 1;
}
my $products = $self->products;
if (scalar(@$products) && !$params->{'remove_from_products'}) {
$cantdelete = 1;
}
my $flag_types = $self->flag_types;
if (scalar(@$flag_types) && !$params->{'remove_from_flags'}) {
$cantdelete = 1;
}
my $cantdelete =
@{$self->members_non_inherited} && !$params->{remove_from_users} ||
@{$self->bugs} && !$params->{remove_from_bugs} ||
@{$self->products} && !$params->{remove_from_products} ||
@{$self->flag_types} && !$params->{remove_from_flags};
ThrowUserError('group_cannot_delete', { group => $self }) if $cantdelete;
}
sub remove_from_db {
sub remove_from_db
{
my $self = shift;
my $dbh = Bugzilla->dbh;
$self->check_remove(@_);
$dbh->bz_start_transaction();
Bugzilla::Hook::process('group_before_delete', { group => $self });
$dbh->do('DELETE FROM whine_schedules
WHERE mailto_type = ? AND mailto = ?',
undef, MAILTO_GROUP, $self->id);
# All the other tables will be handled by foreign keys when we
# drop the main "groups" row.
$dbh->do(
'DELETE FROM whine_schedules WHERE mailto_type = ? AND mailto = ?',
undef, MAILTO_GROUP, $self->id
);
# All the other tables will be handled by foreign keys when we drop the main "groups" row.
$self->SUPER::remove_from_db(@_);
$dbh->bz_commit_transaction();
}
# Add missing entries in bug_group_map for bugs created while
# a mandatory group was disabled and which is now enabled again.
sub _enforce_mandatory {
sub _enforce_mandatory
{
my ($self) = @_;
my $dbh = Bugzilla->dbh;
my $gid = $self->id;
my $bug_ids =
$dbh->selectcol_arrayref('SELECT bugs.bug_id
FROM bugs
INNER JOIN group_control_map
ON group_control_map.product_id = bugs.product_id
LEFT JOIN bug_group_map
ON bug_group_map.bug_id = bugs.bug_id
AND bug_group_map.group_id = group_control_map.group_id
WHERE group_control_map.group_id = ?
AND group_control_map.membercontrol = ?
AND bug_group_map.group_id IS NULL',
undef, ($gid, CONTROLMAPMANDATORY));
my $bug_ids = $dbh->selectcol_arrayref(
'SELECT b.bug_id FROM bugs b'.
' INNER JOIN group_control_map gcm ON gcm.product_id = b.product_id'.
' LEFT JOIN bug_group_map bgm ON bgm.bug_id = b.bug_id AND bgm.group_id = gcm.group_id'.
' WHERE gcm.group_id = ? AND gcm.membercontrol = ? AND bgm.group_id IS NULL',
undef, $gid, CONTROLMAPMANDATORY
);
my $sth = $dbh->prepare('INSERT INTO bug_group_map (bug_id, group_id) VALUES (?, ?)');
foreach my $bug_id (@$bug_ids) {
foreach my $bug_id (@$bug_ids)
{
$sth->execute($bug_id, $gid);
}
}
sub is_active_bug_group {
sub is_active_bug_group
{
my $self = shift;
return $self->is_active && $self->is_bug_group;
}
sub _rederive_regexp {
sub _rederive_regexp
{
my ($self) = @_;
my $dbh = Bugzilla->dbh;
my $sth = $dbh->prepare("SELECT userid, login_name, group_id
FROM profiles
LEFT JOIN user_group_map
ON user_group_map.user_id = profiles.userid
AND group_id = ?
AND grant_type = ?
AND isbless = 0");
my $sthadd = $dbh->prepare("INSERT INTO user_group_map
(user_id, group_id, grant_type, isbless)
VALUES (?, ?, ?, 0)");
my $sthdel = $dbh->prepare("DELETE FROM user_group_map
WHERE user_id = ? AND group_id = ?
AND grant_type = ? and isbless = 0");
my $sth = $dbh->prepare(
"SELECT userid, login_name, group_id FROM profiles".
" LEFT JOIN user_group_map ON user_group_map.user_id = profiles.userid".
" AND group_id = ? AND grant_type = ? AND isbless = 0"
);
my $sthadd = $dbh->prepare(
"INSERT INTO user_group_map (user_id, group_id, grant_type, isbless) VALUES (?, ?, ?, 0)"
);
my $sthdel = $dbh->prepare(
"DELETE FROM user_group_map WHERE user_id=? AND group_id=? AND grant_type=? AND isbless=0"
);
$sth->execute($self->id, GRANT_REGEXP);
my $regexp = $self->user_regexp;
while (my ($uid, $login, $present) = $sth->fetchrow_array) {
if ($regexp ne '' and $login =~ /$regexp/i) {
while (my ($uid, $login, $present) = $sth->fetchrow_array)
{
if ($regexp ne '' && $login =~ /$regexp/i)
{
$sthadd->execute($uid, $self->id, GRANT_REGEXP) unless $present;
} else {
}
else
{
$sthdel->execute($uid, $self->id, GRANT_REGEXP) if $present;
}
}
}
sub flatten_group_membership {
sub flatten_group_membership
{
my ($self, @groups) = @_;
my $dbh = Bugzilla->dbh;
my $sth;
my @groupidstocheck = @groups;
my %groupidschecked = ();
$sth = $dbh->prepare("SELECT member_id FROM group_group_map
WHERE grantor_id = ?
AND grant_type = " . GROUP_MEMBERSHIP);
while (my $node = shift @groupidstocheck) {
$sth = $dbh->prepare(
"SELECT member_id FROM group_group_map".
" WHERE grantor_id = ? AND grant_type = " . GROUP_MEMBERSHIP
);
while (my $node = shift @groupidstocheck)
{
$sth->execute($node);
my $member;
while (($member) = $sth->fetchrow_array) {
if (!$groupidschecked{$member}) {
while (($member) = $sth->fetchrow_array)
{
if (!$groupidschecked{$member})
{
$groupidschecked{$member} = 1;
push @groupidstocheck, $member;
push @groups, $member unless grep $_ == $member, @groups;
@ -456,13 +464,16 @@ sub flatten_group_membership {
##### Module Subroutines ###
################################
sub create {
sub create
{
my $class = shift;
my ($params) = @_;
my $dbh = Bugzilla->dbh;
print get_text('install_group_create', { name => $params->{name} }) . "\n"
if Bugzilla->usage_mode == USAGE_MODE_CMDLINE;
if (Bugzilla->usage_mode == USAGE_MODE_CMDLINE)
{
print get_text('install_group_create', { name => $params->{name} }) . "\n";
}
$dbh->bz_start_transaction();
@ -473,10 +484,11 @@ sub create {
my $admin = new Bugzilla::Group({name => 'admin'});
# This function is also used to create the "admin" group itself,
# so there's a chance it won't exist yet.
if ($admin) {
my $sth = $dbh->prepare('INSERT INTO group_group_map
(member_id, grantor_id, grant_type)
VALUES (?, ?, ?)');
if ($admin)
{
my $sth = $dbh->prepare(
'INSERT INTO group_group_map (member_id, grantor_id, grant_type) VALUES (?, ?, ?)'
);
$sth->execute($admin->id, $group->id, GROUP_MEMBERSHIP);
$sth->execute($admin->id, $group->id, GROUP_BLESS);
$sth->execute($admin->id, $group->id, GROUP_VISIBLE);
@ -489,18 +501,20 @@ sub create {
return $group;
}
sub ValidateGroupName {
sub ValidateGroupName
{
my ($name, @users) = (@_);
my $dbh = Bugzilla->dbh;
my $query = "SELECT id FROM groups " .
"WHERE name = ?";
if (Bugzilla->params->{'usevisibilitygroups'}) {
my $query = "SELECT id FROM groups WHERE name = ?";
if (Bugzilla->params->{usevisibilitygroups})
{
my @visible = (-1);
foreach my $user (@users) {
foreach my $user (@users)
{
$user && push @visible, @{$user->visible_groups_direct};
}
my $visible = join(', ', @visible);
$query .= " AND id IN($visible)";
my $visible = join ', ', @visible;
$query .= " AND id IN ($visible)";
}
my $sth = $dbh->prepare($query);
$sth->execute($name);
@ -542,37 +556,36 @@ sub get_per_group_permissions
### Validators ###
###############################
sub _check_name {
sub _check_name
{
my ($invocant, $name) = @_;
$name = trim($name);
$name || ThrowUserError("empty_group_name");
# If we're creating a Group or changing the name...
if (!ref($invocant) || lc($invocant->name) ne lc($name)) {
if (!ref $invocant || lc($invocant->name) ne lc($name))
{
my $exists = new Bugzilla::Group({name => $name });
ThrowUserError("group_exists", { name => $name }) if $exists;
}
return $name;
}
sub _check_description {
sub _check_description
{
my ($invocant, $desc) = @_;
$desc = trim($desc);
$desc || ThrowUserError("empty_group_description");
return $desc;
}
sub _check_user_regexp {
sub _check_user_regexp
{
my ($invocant, $regex) = @_;
$regex = trim($regex) || '';
ThrowUserError("invalid_regexp") unless (eval {qr/$regex/});
return $regex;
}
sub _check_is_active { return $_[1] ? 1 : 0; }
sub _check_is_bug_group {
return $_[1] ? 1 : 0;
}
sub _check_icon_url { return $_[1] ? clean_text($_[1]) : undef; }
1;