Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
bugzilla
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Ivan Ivlev
bugzilla
Commits
edf97ecb
Commit
edf97ecb
authored
Dec 20, 2007
by
mkanat%bugzilla.org
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bug 388147: Move assigned_to and qa_contact updating into Bugzilla::Bug
Patch By Max Kanat-Alexander <mkanat@bugzilla.org> r=LpSolit, a=LpSolit
parent
5b263218
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
260 additions
and
338 deletions
+260
-338
Bug.pm
Bugzilla/Bug.pm
+163
-73
process_bug.cgi
process_bug.cgi
+97
-265
No files found.
Bugzilla/Bug.pm
View file @
edf97ecb
...
...
@@ -74,6 +74,7 @@ sub DB_COLUMNS {
my
@custom_names
=
map
{
$_
->
name
}
@custom
;
return
qw(
alias
assigned_to
bug_file_loc
bug_id
bug_severity
...
...
@@ -86,6 +87,7 @@ sub DB_COLUMNS {
op_sys
priority
product_id
qa_contact
remaining_time
rep_platform
reporter_accessible
...
...
@@ -95,9 +97,7 @@ sub DB_COLUMNS {
target_milestone
version
)
,
'assigned_to AS assigned_to_id'
,
'reporter AS reporter_id'
,
'qa_contact AS qa_contact_id'
,
$dbh
->
sql_date_format
(
'creation_ts'
,
'%Y.%m.%d %H:%i'
)
.
' AS creation_ts'
,
$dbh
->
sql_date_format
(
'deadline'
,
'%Y-%m-%d'
)
.
' AS deadline'
,
@custom_names
;
...
...
@@ -158,8 +158,10 @@ sub VALIDATORS {
};
use
constant
UPDATE_VALIDATORS
=>
{
assigned_to
=>
\&
_check_assigned_to
,
bug_status
=>
\&
_check_bug_status
,
cclist_accessible
=>
\&
Bugzilla::Object::
check_boolean
,
qa_contact
=>
\&
_check_qa_contact
,
reporter_accessible
=>
\&
Bugzilla::Object::
check_boolean
,
resolution
=>
\&
_check_resolution
,
target_milestone
=>
\&
_check_target_milestone
,
...
...
@@ -172,6 +174,7 @@ sub UPDATE_COLUMNS {
my
@custom_names
=
map
{
$_
->
name
}
@custom
;
my
@columns
=
qw(
alias
assigned_to
cclist_accessible
component_id
deadline
...
...
@@ -183,6 +186,7 @@ sub UPDATE_COLUMNS {
op_sys
priority
product_id
qa_contact
remaining_time
rep_platform
reporter_accessible
...
...
@@ -452,9 +456,9 @@ sub run_create_validators {
delete
$params
->
{
component
};
$params
->
{
assigned_to
}
=
$class
->
_check_assigned_to
(
$
component
,
$params
->
{
assigned_to
}
);
$class
->
_check_assigned_to
(
$
params
->
{
assigned_to
},
$component
);
$params
->
{
qa_contact
}
=
$class
->
_check_qa_contact
(
$
component
,
$params
->
{
qa_contact
}
);
$class
->
_check_qa_contact
(
$
params
->
{
qa_contact
},
$component
);
$params
->
{
cc
}
=
$class
->
_check_cc
(
$component
,
$params
->
{
cc
});
# Callers cannot set Reporter, currently.
...
...
@@ -467,8 +471,8 @@ sub run_create_validators {
$params
->
{
remaining_time
}
=
$params
->
{
estimated_time
};
}
$class
->
_check_strict_isolation
(
$p
roduct
,
$params
->
{
cc
},
$params
->
{
assigned_to
},
$params
->
{
qa_contact
}
);
$class
->
_check_strict_isolation
(
$p
arams
->
{
cc
},
$params
->
{
assigned_to
},
$params
->
{
qa_contact
},
$product
);
(
$params
->
{
dependson
},
$params
->
{
blocked
})
=
$class
->
_check_dependencies
(
$params
->
{
dependson
},
$params
->
{
blocked
},
...
...
@@ -545,6 +549,10 @@ sub update {
$from
=
$self
->
{
"_old_${field}_name"
};
$to
=
$self
->
$field
;
}
if
(
grep
(
$_
eq
$field
,
qw(qa_contact assigned_to)
))
{
$from
=
$old_bug
->
$field
->
login
if
$from
;
$to
=
$self
->
$field
->
login
if
$to
;
}
LogActivityEntry
(
$self
->
id
,
$field
,
$from
,
$to
,
Bugzilla
->
user
->
id
,
$delta_ts
);
}
...
...
@@ -814,16 +822,28 @@ sub _check_alias {
}
sub
_check_assigned_to
{
my
(
$invocant
,
$
component
,
$name
)
=
@_
;
my
(
$invocant
,
$
assignee
,
$component
)
=
@_
;
my
$user
=
Bugzilla
->
user
;
$name
=
trim
(
$name
);
# Default assignee is the component owner.
my
$id
;
if
(
!
$user
->
in_group
(
'editbugs'
,
$component
->
product_id
)
||
!
$name
)
{
# If this is a new bug, you can only set the assignee if you have editbugs.
# If you didn't specify the assignee, we use the default assignee.
if
(
!
ref
$invocant
&&
(
!
$user
->
in_group
(
'editbugs'
,
$component
->
product_id
)
||
!
$assignee
))
{
$id
=
$component
->
default_assignee
->
id
;
}
else
{
$id
=
login_to_id
(
$name
,
THROW_ERROR
);
if
(
!
ref
$assignee
)
{
$assignee
=
trim
(
$assignee
);
# When updating a bug, assigned_to can't be empty.
ThrowUserError
(
"reassign_to_empty"
)
if
ref
$invocant
&&
!
$assignee
;
$assignee
=
Bugzilla::
User
->
check
(
$assignee
);
}
$id
=
$assignee
->
id
;
# create() checks this another way, so we don't have to run this
# check during create().
$invocant
->
_check_strict_isolation_for_user
(
$assignee
)
if
ref
$invocant
;
}
return
$id
;
}
...
...
@@ -1134,6 +1154,38 @@ sub _check_priority {
return
$priority
;
}
sub
_check_qa_contact
{
my
(
$invocant
,
$qa_contact
,
$component
)
=
@_
;
$qa_contact
=
trim
(
$qa_contact
)
if
!
ref
$qa_contact
;
my
$id
;
if
(
!
ref
$invocant
)
{
# Bugs get no QA Contact on creation if useqacontact is off.
return
undef
if
!
Bugzilla
->
params
->
{
useqacontact
};
# Set the default QA Contact if one isn't specified or if the
# user doesn't have editbugs.
if
(
!
Bugzilla
->
user
->
in_group
(
'editbugs'
,
$component
->
product_id
)
||
!
$qa_contact
)
{
$id
=
$component
->
default_qa_contact
->
id
;
}
}
# If a QA Contact was specified or if we're updating, check
# the QA Contact for validity.
if
(
!
defined
$id
&&
$qa_contact
)
{
$qa_contact
=
Bugzilla::
User
->
check
(
$qa_contact
)
if
!
ref
$qa_contact
;
$id
=
$qa_contact
->
id
;
# create() checks this another way, so we don't have to run this
# check during create().
$invocant
->
_check_strict_isolation_for_user
(
$qa_contact
)
if
ref
$invocant
;
}
# "0" always means "undef", for QA Contact.
return
$id
||
undef
;
}
sub
_check_remaining_time
{
return
$_
[
0
]
->
_check_time
(
$_
[
1
],
'remaining_time'
);
}
...
...
@@ -1167,33 +1219,69 @@ sub _check_status_whiteboard { return defined $_[1] ? $_[1] : ''; }
# Unlike other checkers, this one doesn't return anything.
sub
_check_strict_isolation
{
my
(
$invocant
,
$product
,
$cc_ids
,
$assignee_id
,
$qa_contact_id
)
=
@_
;
my
(
$invocant
,
$ccs
,
$assignee
,
$qa_contact
,
$product
)
=
@_
;
return
unless
Bugzilla
->
params
->
{
'strict_isolation'
};
my
@related_users
=
@$cc_ids
;
push
(
@related_users
,
$assignee_id
);
if
(
ref
$invocant
)
{
my
$original
=
$invocant
->
new
(
$invocant
->
id
);
# We only check people if they've been added. This way, if
# strict_isolation is turned on when there are invalid users
# on bugs, people can still add comments and so on.
my
@old_cc
=
map
{
$_
->
id
}
@
{
$original
->
cc_users
};
my
@new_cc
=
map
{
$_
->
id
}
@
{
$invocant
->
cc_users
};
my
(
$removed
,
$added
)
=
diff_arrays
(
\
@old_cc
,
\
@new_cc
);
$ccs
=
$added
;
$assignee
=
$invocant
->
assigned_to
if
$invocant
->
assigned_to
->
id
!=
$original
->
assigned_to
->
id
;
$qa_contact
=
$invocant
->
qa_contact
if
$invocant
->
qa_contact
->
id
!=
$original
->
qa_contact
->
id
;
$product
=
$invocant
->
product
;
}
my
@related_users
=
@$ccs
;
push
(
@related_users
,
$assignee
)
if
$assignee
;
if
(
Bugzilla
->
params
->
{
'useqacontact'
}
&&
$qa_contact
_id
)
{
push
(
@related_users
,
$qa_contact
_id
);
if
(
Bugzilla
->
params
->
{
'useqacontact'
}
&&
$qa_contact
)
{
push
(
@related_users
,
$qa_contact
);
}
@related_users
=
@
{
Bugzilla::
User
->
new_from_list
(
\
@related_users
)}
if
!
ref
$invocant
;
# For each unique user in @related_users...(assignee and qa_contact
# could be duplicates of users in the CC list)
my
%
unique_users
=
map
{
$_
=>
1
}
@related_users
;
my
%
unique_users
=
map
{
$_
->
id
=>
$_
}
@related_users
;
my
@blocked_users
;
foreach
my
$
p
id
(
keys
%
unique_users
)
{
my
$related_user
=
Bugzilla::
User
->
new
(
$pid
)
;
foreach
my
$id
(
keys
%
unique_users
)
{
my
$related_user
=
$unique_users
{
$id
}
;
if
(
!
$related_user
->
can_edit_product
(
$product
->
id
)
||
!
$related_user
->
can_see_product
(
$product
->
id
))
{
push
(
@blocked_users
,
$related_user
->
login
);
}
}
if
(
scalar
(
@blocked_users
))
{
ThrowUserError
(
"invalid_user_group"
,
{
'users'
=>
\
@blocked_users
,
'new'
=>
1
,
'product'
=>
$product
->
name
});
my
%
vars
=
(
users
=>
\
@blocked_users
,
product
=>
$product
->
name
);
if
(
ref
$invocant
)
{
$vars
{
'bug_id'
}
=
$invocant
->
id
;
}
else
{
$vars
{
'new'
}
=
1
;
}
ThrowUserError
(
"invalid_user_group"
,
\%
vars
);
}
}
# This is used by various set_ checkers, to make their code simpler.
sub
_check_strict_isolation_for_user
{
my
(
$self
,
$user
)
=
@_
;
return
unless
Bugzilla
->
params
->
{
"strict_isolation"
};
if
(
!
$user
->
can_edit_product
(
$self
->
{
product_id
}))
{
ThrowUserError
(
'invalid_user_group'
,
{
users
=>
$user
->
login
,
product
=>
$self
->
product
,
bug_id
=>
$self
->
id
});
}
}
...
...
@@ -1223,25 +1311,6 @@ sub _check_time {
return
$time
;
}
sub
_check_qa_contact
{
my
(
$invocant
,
$component
,
$name
)
=
@_
;
my
$user
=
Bugzilla
->
user
;
return
undef
unless
Bugzilla
->
params
->
{
'useqacontact'
};
$name
=
trim
(
$name
);
my
$id
;
if
(
!
$user
->
in_group
(
'editbugs'
,
$component
->
product_id
)
||
!
$name
)
{
# We want to insert NULL into the database if we get a 0.
$id
=
$component
->
default_qa_contact
->
id
||
undef
;
}
else
{
$id
=
login_to_id
(
$name
,
THROW_ERROR
);
}
return
$id
;
}
sub
_check_version
{
my
(
$invocant
,
$version
,
$product
)
=
@_
;
$version
=
trim
(
$version
);
...
...
@@ -1331,13 +1400,21 @@ sub fields {
# To run check_can_change_field.
sub
_set_global_validator
{
my
(
$self
,
$value
,
$field
)
=
@_
;
my
$current
_value
=
$self
->
$field
;
my
$current
=
$self
->
$field
;
my
$privs
;
$self
->
check_can_change_field
(
$field
,
$current_value
,
$value
,
\
$privs
)
||
ThrowUserError
(
'illegal_change'
,
{
field
=>
$field
,
oldvalue
=>
$current_value
,
newvalue
=>
$value
,
privs
=>
$privs
});
$current
=
$current
->
id
if
ref
$current
&&
$current
->
isa
(
'Bugzilla::Object'
);
$value
=
$value
->
id
if
ref
$value
&&
$value
->
isa
(
'Bugzilla::Object'
);
my
$can
=
$self
->
check_can_change_field
(
$field
,
$current
,
$value
,
\
$privs
);
if
(
!
$can
)
{
if
(
$field
eq
'assigned_to'
||
$field
eq
'qa_contact'
)
{
$value
=
user_id_to_login
(
$value
);
$current
=
user_id_to_login
(
$current
);
}
ThrowUserError
(
'illegal_change'
,
{
field
=>
$field
,
oldvalue
=>
$current
,
newvalue
=>
$value
,
privs
=>
$privs
});
}
}
...
...
@@ -1346,6 +1423,16 @@ sub _set_global_validator {
#################
sub
set_alias
{
$_
[
0
]
->
set
(
'alias'
,
$_
[
1
]);
}
sub
set_assigned_to
{
my
(
$self
,
$value
)
=
@_
;
$self
->
set
(
'assigned_to'
,
$value
);
delete
$self
->
{
'assigned_to_obj'
};
}
sub
reset_assigned_to
{
my
$self
=
shift
;
my
$comp
=
$self
->
component_obj
;
$self
->
set_assigned_to
(
$comp
->
default_assignee
);
}
sub
set_cclist_accessible
{
$_
[
0
]
->
set
(
'cclist_accessible'
,
$_
[
1
]);
}
sub
set_comment_is_private
{
my
(
$self
,
$comment_id
,
$isprivate
)
=
@_
;
...
...
@@ -1505,6 +1592,16 @@ sub set_product {
return
$product_changed
;
}
sub
set_qa_contact
{
my
(
$self
,
$value
)
=
@_
;
$self
->
set
(
'qa_contact'
,
$value
);
delete
$self
->
{
'qa_contact_obj'
};
}
sub
reset_qa_contact
{
my
$self
=
shift
;
my
$comp
=
$self
->
component_obj
;
$self
->
set_qa_contact
(
$comp
->
default_qa_contact
);
}
sub
set_remaining_time
{
$_
[
0
]
->
set
(
'remaining_time'
,
$_
[
1
]);
}
# Used only when closing a bug or moving between closed states.
sub
_zero_remaining_time
{
$_
[
0
]
->
{
'remaining_time'
}
=
0
;
}
...
...
@@ -1512,9 +1609,9 @@ sub set_reporter_accessible { $_[0]->set('reporter_accessible', $_[1]); }
sub
set_resolution
{
$_
[
0
]
->
set
(
'resolution'
,
$_
[
1
]);
}
sub
clear_resolution
{
$_
[
0
]
->
{
'resolution'
}
=
''
}
sub
set_severity
{
$_
[
0
]
->
set
(
'bug_severity'
,
$_
[
1
]);
}
sub
set_status
{
sub
set_status
{
my
(
$self
,
$status
)
=
@_
;
$self
->
set
(
'bug_status'
,
$status
);
$self
->
set
(
'bug_status'
,
$status
);
# Check for the everconfirmed transition
$self
->
_set_everconfirmed
(
1
)
if
(
is_open_state
(
$status
)
&&
$status
ne
'UNCONFIRMED'
);
}
...
...
@@ -1537,14 +1634,7 @@ sub add_cc {
return
if
!
$user_or_name
;
my
$user
=
ref
$user_or_name
?
$user_or_name
:
Bugzilla::
User
->
check
(
$user_or_name
);
if
(
Bugzilla
->
params
->
{
strict_isolation
}
&&
!
$user
->
can_edit_product
(
$self
->
product_obj
->
id
))
{
ThrowUserError
(
'invalid_user_group'
,
{
users
=>
$user
->
login
,
bug_id
=>
$self
->
id
});
}
$self
->
_check_strict_isolation_for_user
(
$user
);
my
$cc_users
=
$self
->
cc_users
;
push
(
@$cc_users
,
$user
)
if
!
grep
(
$_
->
id
==
$user
->
id
,
@$cc_users
);
}
...
...
@@ -1729,10 +1819,10 @@ sub attachments {
sub
assigned_to
{
my
(
$self
)
=
@_
;
return
$self
->
{
'assigned_to
'
}
if
exists
$self
->
{
'assigned_to
'
};
$self
->
{
'assigned_to
_id
'
}
=
0
if
$self
->
{
'error'
};
$self
->
{
'assigned_to
'
}
=
new
Bugzilla::
User
(
$self
->
{
'assigned_to_id
'
});
return
$self
->
{
'assigned_to'
};
return
$self
->
{
'assigned_to
_obj'
}
if
exists
$self
->
{
'assigned_to_obj
'
};
$self
->
{
'assigned_to'
}
=
0
if
$self
->
{
'error'
};
$self
->
{
'assigned_to
_obj'
}
||=
new
Bugzilla::
User
(
$self
->
{
'assigned_to
'
});
return
$self
->
{
'assigned_to
_obj
'
};
}
sub
blocked
{
...
...
@@ -1914,18 +2004,18 @@ sub product_obj {
sub
qa_contact
{
my
(
$self
)
=
@_
;
return
$self
->
{
'qa_contact
'
}
if
exists
$self
->
{
'qa_contact
'
};
return
$self
->
{
'qa_contact
_obj'
}
if
exists
$self
->
{
'qa_contact_obj
'
};
return
undef
if
$self
->
{
'error'
};
if
(
Bugzilla
->
params
->
{
'useqacontact'
}
&&
$self
->
{
'qa_contact
_id
'
})
{
$self
->
{
'qa_contact
'
}
=
new
Bugzilla::
User
(
$self
->
{
'qa_contact_id
'
});
if
(
Bugzilla
->
params
->
{
'useqacontact'
}
&&
$self
->
{
'qa_contact'
})
{
$self
->
{
'qa_contact
_obj'
}
=
new
Bugzilla::
User
(
$self
->
{
'qa_contact
'
});
}
else
{
# XXX - This is somewhat inconsistent with the assignee/reporter
# methods, which will return an empty User if they get a 0.
# However, we're keeping it this way now, for backwards-compatibility.
$self
->
{
'qa_contact'
}
=
undef
;
$self
->
{
'qa_contact
_obj
'
}
=
undef
;
}
return
$self
->
{
'qa_contact'
};
return
$self
->
{
'qa_contact
_obj
'
};
}
sub
reporter
{
...
...
@@ -2065,10 +2155,10 @@ sub user {
my
$unknown_privileges
=
$user
->
in_group
(
'editbugs'
,
$prod_id
);
my
$canedit
=
$unknown_privileges
||
$user
->
id
==
$self
->
{
assigned_to_id
}
||
$user
->
id
==
$self
->
{
'assigned_to'
}
||
(
Bugzilla
->
params
->
{
'useqacontact'
}
&&
$self
->
{
'qa_contact
_id
'
}
&&
$user
->
id
==
$self
->
{
qa_contact_id
});
&&
$self
->
{
'qa_contact'
}
&&
$user
->
id
==
$self
->
{
'qa_contact'
});
my
$canconfirm
=
$unknown_privileges
||
$user
->
in_group
(
'canconfirm'
,
$prod_id
);
my
$isreporter
=
$user
->
id
...
...
@@ -2991,14 +3081,14 @@ sub check_can_change_field {
# Make sure that a valid bug ID has been given.
if
(
!
$self
->
{
'error'
})
{
# Allow the assignee to change anything else.
if
(
$self
->
{
'assigned_to
_id
'
}
==
$user
->
id
)
{
if
(
$self
->
{
'assigned_to'
}
==
$user
->
id
)
{
return
1
;
}
# Allow the QA contact to change anything else.
if
(
Bugzilla
->
params
->
{
'useqacontact'
}
&&
$self
->
{
'qa_contact
_id
'
}
&&
(
$self
->
{
'qa_contact
_id
'
}
==
$user
->
id
))
&&
$self
->
{
'qa_contact'
}
&&
(
$self
->
{
'qa_contact'
}
==
$user
->
id
))
{
return
1
;
}
...
...
process_bug.cgi
View file @
edf97ecb
...
...
@@ -293,6 +293,13 @@ sub DuplicateUserConfirm {
exit
;
}
my
@set_fields
=
qw(op_sys rep_platform priority bug_severity
component target_milestone version
bug_file_loc status_whiteboard short_desc
deadline remaining_time estimated_time)
;
push
(
@set_fields
,
'assigned_to'
)
if
!
$cgi
->
param
(
'set_default_assignee'
);
push
(
@set_fields
,
'qa_contact'
)
if
!
$cgi
->
param
(
'set_default_qa_contact'
);
my
%
methods
=
(
bug_severity
=>
'set_severity'
,
rep_platform
=>
'set_platform'
,
...
...
@@ -303,97 +310,19 @@ foreach my $b (@bug_objects) {
# Component, target_milestone, and version are in here just in case
# the 'product' field wasn't defined in the CGI. It doesn't hurt to set
# them twice.
foreach
my
$field_name
(
qw(op_sys rep_platform priority bug_severity
component target_milestone version
bug_file_loc status_whiteboard short_desc
deadline remaining_time estimated_time)
)
{
foreach
my
$field_name
(
@set_fields
)
{
if
(
should_set
(
$field_name
))
{
my
$method
=
$methods
{
$field_name
};
$method
||=
"set_"
.
$field_name
;
$b
->
$method
(
$cgi
->
param
(
$field_name
));
}
}
$b
->
reset_assigned_to
if
$cgi
->
param
(
'set_default_assignee'
);
$b
->
reset_qa_contact
if
$cgi
->
param
(
'set_default_qa_contact'
);
}
my
$action
=
trim
(
$cgi
->
param
(
'action'
)
||
''
);
if
(
$action
eq
Bugzilla
->
params
->
{
'move-button-text'
})
{
Bugzilla
->
params
->
{
'move-enabled'
}
||
ThrowUserError
(
"move_bugs_disabled"
);
$user
->
is_mover
||
ThrowUserError
(
"auth_failure"
,
{
action
=>
'move'
,
object
=>
'bugs'
});
my
@multi_select_locks
=
map
{
'bug_'
.
$_
->
name
.
" WRITE"
}
Bugzilla
->
get_fields
({
custom
=>
1
,
type
=>
FIELD_TYPE_MULTI_SELECT
,
obsolete
=>
0
});
$dbh
->
bz_lock_tables
(
'bugs WRITE'
,
'bugs_activity WRITE'
,
'duplicates WRITE'
,
'longdescs WRITE'
,
'profiles READ'
,
'groups READ'
,
'bug_group_map READ'
,
'group_group_map READ'
,
'user_group_map READ'
,
'classifications READ'
,
'products READ'
,
'components READ'
,
'votes READ'
,
'cc READ'
,
'fielddefs READ'
,
'bug_status READ'
,
'status_workflow READ'
,
'resolution READ'
,
@multi_select_locks
);
# First update all moved bugs.
foreach
my
$bug
(
@bug_objects
)
{
$bug
->
add_comment
(
scalar
$cgi
->
param
(
'comment'
),
{
type
=>
CMT_MOVED_TO
,
extra_data
=>
$user
->
login
});
}
# Don't export the new status and resolution. We want the current ones.
local
$
Storable::
forgive_me
=
1
;
my
$bugs
=
dclone
(
\
@bug_objects
);
foreach
my
$bug
(
@bug_objects
)
{
my
(
$status
,
$resolution
)
=
$bug
->
get_new_status_and_resolution
(
'move'
);
$bug
->
set_status
(
$status
);
$bug
->
set_resolution
(
$resolution
);
}
$_
->
update
()
foreach
@bug_objects
;
$dbh
->
bz_unlock_tables
();
# Now send emails.
foreach
my
$id
(
@idlist
)
{
$vars
->
{
'mailrecipients'
}
=
{
'changer'
=>
$user
->
login
};
$vars
->
{
'id'
}
=
$id
;
$vars
->
{
'type'
}
=
"move"
;
send_results
(
$id
,
$vars
);
}
# Prepare and send all data about these bugs to the new database
my
$to
=
Bugzilla
->
params
->
{
'move-to-address'
};
$to
=~
s/@/\@/
;
my
$from
=
Bugzilla
->
params
->
{
'moved-from-address'
};
$from
=~
s/@/\@/
;
my
$msg
=
"To: $to\n"
;
$msg
.=
"From: Bugzilla <"
.
$from
.
">\n"
;
$msg
.=
"Subject: Moving bug(s) "
.
join
(
', '
,
@idlist
)
.
"\n\n"
;
my
@fieldlist
=
(
Bugzilla::
Bug
->
fields
,
'group'
,
'long_desc'
,
'attachment'
,
'attachmentdata'
);
my
%
displayfields
;
foreach
(
@fieldlist
)
{
$displayfields
{
$_
}
=
1
;
}
$template
->
process
(
"bug/show.xml.tmpl"
,
{
bugs
=>
$bugs
,
displayfields
=>
\%
displayfields
,
},
\
$msg
)
||
ThrowTemplateError
(
$template
->
error
());
$msg
.=
"\n"
;
MessageToMTA
(
$msg
);
# End the response page.
unless
(
Bugzilla
->
usage_mode
==
USAGE_MODE_EMAIL
)
{
$template
->
process
(
"bug/navigate.html.tmpl"
,
$vars
)
||
ThrowTemplateError
(
$template
->
error
());
$template
->
process
(
"global/footer.html.tmpl"
,
$vars
)
||
ThrowTemplateError
(
$template
->
error
());
}
exit
;
}
$::query
=
"UPDATE bugs SET"
;
$::comma
=
""
;
local
our
@values
;
...
...
@@ -498,83 +427,93 @@ if (defined $cgi->param('newcc')
foreach
my
$b
(
@bug_objects
)
{
$b
->
remove_cc
(
$_
)
foreach
@cc_remove
;
$b
->
add_cc
(
$_
)
foreach
@cc_add
;
# Theoretically you could move a product without ever specifying
# a new assignee or qa_contact, or adding/removing any CCs. So,
# we have to check that the current assignee, qa, and CCs are still
# valid if we've switched products, under strict_isolation. We can only
# do that here. There ought to be some better way to do this,
# architecturally, but I haven't come up with it.
if
(
$product_change
)
{
$b
->
_check_strict_isolation
();
}
}
# Store the new assignee and QA contact IDs (if any). This is the
# only way to keep these informations when bugs are reassigned by
# component as $cgi->param('assigned_to') and $cgi->param('qa_contact')
# are not the right fields to look at.
# If the assignee or qacontact is changed, the new one is checked when
# changed information is validated. If not, then the unchanged assignee
# or qacontact may have to be validated later.
my
$assignee
;
my
$qacontact
;
my
$qacontact_checked
=
0
;
my
$assignee_checked
=
0
;
my
%
usercache
=
();
if
(
should_set
(
'assigned_to'
)
&&
!
$cgi
->
param
(
'set_default_assignee'
))
{
my
$name
=
trim
(
$cgi
->
param
(
'assigned_to'
));
if
(
$name
ne
""
)
{
$assignee
=
login_to_id
(
$name
,
THROW_ERROR
);
if
(
Bugzilla
->
params
->
{
"strict_isolation"
})
{
$usercache
{
$assignee
}
||=
Bugzilla::
User
->
new
(
$assignee
);
my
$assign_user
=
$usercache
{
$assignee
};
foreach
my
$product_id
(
@newprod_ids
)
{
if
(
!
$assign_user
->
can_edit_product
(
$product_id
))
{
my
$product_name
=
Bugzilla::
Product
->
new
(
$product_id
)
->
name
;
ThrowUserError
(
'invalid_user_group'
,
{
'users'
=>
$assign_user
->
login
,
'product'
=>
$product_name
,
'bug_id'
=>
(
scalar
(
@idlist
)
>
1
)
?
undef
:
$idlist
[
0
]
});
}
}
}
}
else
{
ThrowUserError
(
"reassign_to_empty"
);
if
(
$action
eq
Bugzilla
->
params
->
{
'move-button-text'
})
{
Bugzilla
->
params
->
{
'move-enabled'
}
||
ThrowUserError
(
"move_bugs_disabled"
);
$user
->
is_mover
||
ThrowUserError
(
"auth_failure"
,
{
action
=>
'move'
,
object
=>
'bugs'
});
my
@multi_select_locks
=
map
{
'bug_'
.
$_
->
name
.
" WRITE"
}
Bugzilla
->
get_fields
({
custom
=>
1
,
type
=>
FIELD_TYPE_MULTI_SELECT
,
obsolete
=>
0
});
$dbh
->
bz_lock_tables
(
'bugs WRITE'
,
'bugs_activity WRITE'
,
'duplicates WRITE'
,
'longdescs WRITE'
,
'profiles READ'
,
'groups READ'
,
'bug_group_map READ'
,
'group_group_map READ'
,
'user_group_map READ'
,
'classifications READ'
,
'products READ'
,
'components READ'
,
'votes READ'
,
'cc READ'
,
'fielddefs READ'
,
'bug_status READ'
,
'status_workflow READ'
,
'resolution READ'
,
@multi_select_locks
);
# First update all moved bugs.
foreach
my
$bug
(
@bug_objects
)
{
$bug
->
add_comment
(
scalar
$cgi
->
param
(
'comment'
),
{
type
=>
CMT_MOVED_TO
,
extra_data
=>
$user
->
login
});
}
DoComma
();
$::query
.=
"assigned_to = ?"
;
push
(
@values
,
$assignee
);
$assignee_checked
=
1
;
};
# Don't export the new status and resolution. We want the current ones.
local
$
Storable::
forgive_me
=
1
;
my
$bugs
=
dclone
(
\
@bug_objects
);
foreach
my
$bug
(
@bug_objects
)
{
my
(
$status
,
$resolution
)
=
$bug
->
get_new_status_and_resolution
(
'move'
);
$bug
->
set_status
(
$status
);
$bug
->
set_resolution
(
$resolution
);
}
$_
->
update
()
foreach
@bug_objects
;
$dbh
->
bz_unlock_tables
();
if
(
should_set
(
'qa_contact'
)
&&
!
$cgi
->
param
(
'set_default_qa_contact'
))
{
my
$name
=
trim
(
$cgi
->
param
(
'qa_contact'
));
$qacontact
=
login_to_id
(
$name
,
THROW_ERROR
)
if
(
$name
ne
""
);
if
(
$qacontact
&&
Bugzilla
->
params
->
{
"strict_isolation"
}
&&
!
(
defined
$cgi
->
param
(
'id'
)
&&
$bug
->
qa_contact
&&
$qacontact
==
$bug
->
qa_contact
->
id
))
{
$usercache
{
$qacontact
}
||=
Bugzilla::
User
->
new
(
$qacontact
);
my
$qa_user
=
$usercache
{
$qacontact
};
foreach
my
$product_id
(
@newprod_ids
)
{
if
(
!
$qa_user
->
can_edit_product
(
$product_id
))
{
my
$product_name
=
Bugzilla::
Product
->
new
(
$product_id
)
->
name
;
ThrowUserError
(
'invalid_user_group'
,
{
'users'
=>
$qa_user
->
login
,
'product'
=>
$product_name
,
'bug_id'
=>
(
scalar
(
@idlist
)
>
1
)
?
undef
:
$idlist
[
0
]
});
}
}
# Now send emails.
foreach
my
$id
(
@idlist
)
{
$vars
->
{
'mailrecipients'
}
=
{
'changer'
=>
$user
->
login
};
$vars
->
{
'id'
}
=
$id
;
$vars
->
{
'type'
}
=
"move"
;
send_results
(
$id
,
$vars
);
}
$qacontact_checked
=
1
;
DoComma
();
if
(
$qacontact
)
{
$::query
.=
"qa_contact = ?"
;
push
(
@values
,
$qacontact
);
# Prepare and send all data about these bugs to the new database
my
$to
=
Bugzilla
->
params
->
{
'move-to-address'
};
$to
=~
s/@/\@/
;
my
$from
=
Bugzilla
->
params
->
{
'moved-from-address'
};
$from
=~
s/@/\@/
;
my
$msg
=
"To: $to\n"
;
$msg
.=
"From: Bugzilla <"
.
$from
.
">\n"
;
$msg
.=
"Subject: Moving bug(s) "
.
join
(
', '
,
@idlist
)
.
"\n\n"
;
my
@fieldlist
=
(
Bugzilla::
Bug
->
fields
,
'group'
,
'long_desc'
,
'attachment'
,
'attachmentdata'
);
my
%
displayfields
;
foreach
(
@fieldlist
)
{
$displayfields
{
$_
}
=
1
;
}
else
{
$::query
.=
"qa_contact = NULL"
;
$template
->
process
(
"bug/show.xml.tmpl"
,
{
bugs
=>
$bugs
,
displayfields
=>
\%
displayfields
,
},
\
$msg
)
||
ThrowTemplateError
(
$template
->
error
());
$msg
.=
"\n"
;
MessageToMTA
(
$msg
);
# End the response page.
unless
(
Bugzilla
->
usage_mode
==
USAGE_MODE_EMAIL
)
{
$template
->
process
(
"bug/navigate.html.tmpl"
,
$vars
)
||
ThrowTemplateError
(
$template
->
error
());
$template
->
process
(
"global/footer.html.tmpl"
,
$vars
)
||
ThrowTemplateError
(
$template
->
error
());
}
exit
;
}
if
((
$cgi
->
param
(
'set_default_assignee'
)
||
$cgi
->
param
(
'set_default_qa_contact'
))
&&
Bugzilla
->
params
->
{
'commentonreassignbycomponent'
}
&&
!
comment_exists
())
{
...
...
@@ -661,56 +600,6 @@ sub SnapShotBug {
my
$timestamp
;
if
(
$product_change
&&
Bugzilla
->
params
->
{
"strict_isolation"
})
{
my
$sth_cc
=
$dbh
->
prepare
(
"SELECT who
FROM cc
WHERE bug_id = ?"
);
my
$sth_bug
=
$dbh
->
prepare
(
"SELECT assigned_to, qa_contact
FROM bugs
WHERE bug_id = ?"
);
foreach
my
$id
(
@idlist
)
{
$sth_cc
->
execute
(
$id
);
my
@blocked_cc
=
();
while
(
my
(
$pid
)
=
$sth_cc
->
fetchrow_array
)
{
# Ignore deleted accounts. They will never get notification.
$usercache
{
$pid
}
||=
Bugzilla::
User
->
new
(
$pid
)
||
next
;
my
$cc_user
=
$usercache
{
$pid
};
if
(
!
$cc_user
->
can_edit_product
(
$product
->
id
))
{
push
(
@blocked_cc
,
$cc_user
->
login
);
}
}
if
(
scalar
(
@blocked_cc
))
{
ThrowUserError
(
'invalid_user_group'
,
{
'users'
=>
\
@blocked_cc
,
'bug_id'
=>
$id
,
'product'
=>
$product
->
name
});
}
$sth_bug
->
execute
(
$id
);
my
(
$assignee
,
$qacontact
)
=
$sth_bug
->
fetchrow_array
;
if
(
!
$assignee_checked
)
{
$usercache
{
$assignee
}
||=
Bugzilla::
User
->
new
(
$assignee
)
||
next
;
my
$assign_user
=
$usercache
{
$assignee
};
if
(
!
$assign_user
->
can_edit_product
(
$product
->
id
))
{
ThrowUserError
(
'invalid_user_group'
,
{
'users'
=>
$assign_user
->
login
,
'bug_id'
=>
$id
,
'product'
=>
$product
->
name
});
}
}
if
(
!
$qacontact_checked
&&
$qacontact
)
{
$usercache
{
$qacontact
}
||=
Bugzilla::
User
->
new
(
$qacontact
)
||
next
;
my
$qa_user
=
$usercache
{
$qacontact
};
if
(
!
$qa_user
->
can_edit_product
(
$product
->
id
))
{
ThrowUserError
(
'invalid_user_group'
,
{
'users'
=>
$qa_user
->
login
,
'bug_id'
=>
$id
,
'product'
=>
$product
->
name
});
}
}
}
}
my
%
bug_objects
=
map
{
$_
->
id
=>
$_
}
@bug_objects
;
# This loop iterates once for each bug to be processed (i.e. all the
...
...
@@ -751,35 +640,6 @@ foreach my $id (@idlist) {
$comma
=
','
;
}
# We have to check whether the bug is moved to another product
# and/or component before reassigning.
if
(
$cgi
->
param
(
'set_default_assignee'
))
{
my
$new_comp_id
=
$bug_objects
{
$id
}
->
component_id
;
$assignee
=
$dbh
->
selectrow_array
(
'SELECT initialowner
FROM components
WHERE components.id = ?'
,
undef
,
$new_comp_id
);
$query
.=
"$comma assigned_to = ?"
;
push
(
@bug_values
,
$assignee
);
$comma
=
','
;
}
if
(
Bugzilla
->
params
->
{
'useqacontact'
}
&&
$cgi
->
param
(
'set_default_qa_contact'
))
{
my
$new_comp_id
=
$bug_objects
{
$id
}
->
component_id
;
$qacontact
=
$dbh
->
selectrow_array
(
'SELECT initialqacontact
FROM components
WHERE components.id = ?'
,
undef
,
$new_comp_id
);
if
(
$qacontact
)
{
$query
.=
"$comma qa_contact = ?"
;
push
(
@bug_values
,
$qacontact
);
}
else
{
$query
.=
"$comma qa_contact = NULL"
;
}
$comma
=
','
;
}
my
$bug_changed
=
0
;
my
$write
=
"WRITE"
;
# Might want to make a param to control
# whether we do LOW_PRIORITY ...
...
...
@@ -826,14 +686,11 @@ foreach my $id (@idlist) {
$formhash
{
'bug_status'
}
=
$status
;
$formhash
{
'resolution'
}
=
$resolution
;
# We need to convert $newhash{'assigned_to'} and $newhash{'qa_contact'}
# email addresses into their corresponding IDs;
$formhash
{
'qa_contact'
}
=
$qacontact
if
Bugzilla
->
params
->
{
'useqacontact'
};
$formhash
{
'assigned_to'
}
=
$assignee
;
# This hash is required by Bug::check_can_change_field().
my
$cgi_hash
=
{
'dontchange'
=>
scalar
$cgi
->
param
(
'dontchange'
)};
foreach
my
$col
(
@editable_bug_fields
)
{
# XXX - Ugly workaround which has to go away before 3.1.3.
next
if
(
$col
eq
'assigned_to'
||
$col
eq
'qa_contact'
);
if
(
exists
$formhash
{
$col
}
&&
!
$old_bug_obj
->
check_can_change_field
(
$col
,
$oldhash
{
$col
},
$formhash
{
$col
},
\
$PrivilegesRequired
,
$cgi_hash
))
...
...
@@ -844,11 +701,6 @@ foreach my $id (@idlist) {
$vars
->
{
'oldvalue'
}
=
$old_bug_obj
->
component
;
$vars
->
{
'newvalue'
}
=
$cgi
->
param
(
'component'
);
$vars
->
{
'field'
}
=
'component'
;
}
elsif
(
$col
eq
'assigned_to'
||
$col
eq
'qa_contact'
)
{
# Display the assignee or QA contact email address
$vars
->
{
'oldvalue'
}
=
user_id_to_login
(
$oldhash
{
$col
});
$vars
->
{
'newvalue'
}
=
user_id_to_login
(
$formhash
{
$col
});
$vars
->
{
'field'
}
=
$col
;
}
else
{
$vars
->
{
'oldvalue'
}
=
$oldhash
{
$col
};
$vars
->
{
'newvalue'
}
=
$formhash
{
$col
};
...
...
@@ -1034,11 +886,6 @@ foreach my $id (@idlist) {
$newhash
{
$col
}
=
$newvalues
[
$i
];
$i
++
;
}
# for passing to Bugzilla::BugMail to ensure that when someone is removed
# from one of these fields, they get notified of that fact (if desired)
#
my
$origOwner
=
""
;
my
$origQaContact
=
""
;
# $msgs will store emails which have to be sent to voters, if any.
my
$msgs
;
...
...
@@ -1051,27 +898,10 @@ foreach my $id (@idlist) {
my
$new
=
shift
@newvalues
;
if
(
$old
ne
$new
)
{
# save off the old value for passing to Bugzilla::BugMail so
# the old assignee can be notified
#
if
(
$col
eq
'assigned_to'
)
{
$old
=
(
$old
)
?
user_id_to_login
(
$old
)
:
""
;
$new
=
(
$new
)
?
user_id_to_login
(
$new
)
:
""
;
$origOwner
=
$old
;
}
# ditto for the old qa contact
#
if
(
$col
eq
'qa_contact'
)
{
$old
=
(
$old
)
?
user_id_to_login
(
$old
)
:
""
;
$new
=
(
$new
)
?
user_id_to_login
(
$new
)
:
""
;
$origQaContact
=
$old
;
}
# Bugzilla::Bug does these for us already.
next
if
grep
(
$_
eq
$col
,
qw(keywords op_sys rep_platform priority
product_id component_id version
target_milestone
target_milestone
assigned_to qa_contact
bug_severity short_desc alias
deadline estimated_time remaining_time
reporter_accessible cclist_accessible
...
...
@@ -1147,10 +977,12 @@ foreach my $id (@idlist) {
# all concerned users, including the bug itself, but also the
# duplicated bug and dependent bugs, if any.
$vars
->
{
'mailrecipients'
}
=
{
'cc'
=>
$cc_removed
,
'owner'
=>
$origOwner
,
'qacontact'
=>
$origQaContact
,
'changer'
=>
Bugzilla
->
user
->
login
};
my
$orig_qa
=
$old_bug_obj
->
qa_contact
;
$vars
->
{
'mailrecipients'
}
=
{
cc
=>
$cc_removed
,
owner
=>
$old_bug_obj
->
assigned_to
->
login
,
qacontact
=>
$orig_qa
?
$orig_qa
->
login
:
''
,
changer
=>
Bugzilla
->
user
->
login
};
$vars
->
{
'id'
}
=
$id
;
$vars
->
{
'type'
}
=
"bug"
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment