summaryrefslogtreecommitdiffstats
path: root/Bugzilla
diff options
context:
space:
mode:
authorJesse Clark <jjclark1982@gmail.com>2010-02-08 01:10:03 +0100
committerMax Kanat-Alexander <mkanat@bugzilla.org>2010-02-08 01:10:03 +0100
commitd73a83506def7c6b43e5ad720777ec700f6af2e8 (patch)
treeee858870f5355c6551ee18546a82269df2602592 /Bugzilla
parent463c56db162f0b6e13a87c2499557f8dba7b9644 (diff)
downloadbugzilla-d73a83506def7c6b43e5ad720777ec700f6af2e8.tar.gz
bugzilla-d73a83506def7c6b43e5ad720777ec700f6af2e8.tar.xz
Bug 251556: Allow "Bug ID" fields to have one-way mutual relationships (like blocks/dependson)
r=mkanat, a=mkanat
Diffstat (limited to 'Bugzilla')
-rw-r--r--Bugzilla/Bug.pm47
-rw-r--r--Bugzilla/DB/Schema.pm1
-rw-r--r--Bugzilla/Field.pm66
-rw-r--r--Bugzilla/Install/DB.pm3
4 files changed, 116 insertions, 1 deletions
diff --git a/Bugzilla/Bug.pm b/Bugzilla/Bug.pm
index fd28b5b82..1e418aa18 100644
--- a/Bugzilla/Bug.pm
+++ b/Bugzilla/Bug.pm
@@ -25,6 +25,7 @@
# Max Kanat-Alexander <mkanat@bugzilla.org>
# Frédéric Buclin <LpSolit@gmail.com>
# Lance Larsh <lance.larsh@oracle.com>
+# Elliotte Martin <elliotte_martin@yahoo.com>
package Bugzilla::Bug;
@@ -1761,7 +1762,42 @@ sub _check_select_field {
sub _check_bugid_field {
my ($invocant, $value, $field) = @_;
return undef if !$value;
- return $invocant->check($value, $field)->id;
+
+ # check that the value is a valid, visible bug id
+ my $checked_id = $invocant->check($value, $field)->id;
+
+ # check for loop (can't have a loop if this is a new bug)
+ if (ref $invocant) {
+ _check_relationship_loop($field, $invocant->bug_id, $checked_id);
+ }
+
+ return $checked_id;
+}
+
+sub _check_relationship_loop {
+ # Generates a dependency tree for a given bug. Calls itself recursively
+ # to generate sub-trees for the bug's dependencies.
+ my ($field, $bug_id, $dep_id, $ids) = @_;
+
+ # Don't do anything if this bug doesn't have any dependencies.
+ return unless defined($dep_id);
+
+ # Check whether we have seen this bug yet
+ $ids = {} unless defined $ids;
+ $ids->{$bug_id} = 1;
+ if ($ids->{$dep_id}) {
+ ThrowUserError("relationship_loop_single", {
+ 'bug_id' => $bug_id,
+ 'dep_id' => $dep_id,
+ 'field_name' => $field});
+ }
+
+ # Get this dependency's record from the database
+ my $dbh = Bugzilla->dbh;
+ my $next_dep_id = $dbh->selectrow_array(
+ "SELECT $field FROM bugs WHERE bug_id = ?", undef, $dep_id);
+
+ _check_relationship_loop($field, $dep_id, $next_dep_id, $ids);
}
#####################################################################
@@ -2553,6 +2589,15 @@ sub blocked {
# Even bugs in an error state always have a bug_id.
sub bug_id { $_[0]->{'bug_id'}; }
+sub related_bugs {
+ my ($self, $relationship) = @_;
+ return [] if $self->{'error'};
+
+ my $field_name = $relationship->name;
+ $self->{'related_bugs'}->{$field_name} ||= $self->match({$field_name => $self->id});
+ return $self->{'related_bugs'}->{$field_name};
+}
+
sub cc {
my ($self) = @_;
return $self->{'cc'} if exists $self->{'cc'};
diff --git a/Bugzilla/DB/Schema.pm b/Bugzilla/DB/Schema.pm
index 8bee5dfe1..44d224d57 100644
--- a/Bugzilla/DB/Schema.pm
+++ b/Bugzilla/DB/Schema.pm
@@ -693,6 +693,7 @@ use constant ABSTRACT_SCHEMA => {
value_field_id => {TYPE => 'INT3',
REFERENCES => {TABLE => 'fielddefs',
COLUMN => 'id'}},
+ reverse_desc => {TYPE => 'TINYTEXT'},
],
INDEXES => [
fielddefs_name_idx => {FIELDS => ['name'],
diff --git a/Bugzilla/Field.pm b/Bugzilla/Field.pm
index 2f14037ab..17e4194c2 100644
--- a/Bugzilla/Field.pm
+++ b/Bugzilla/Field.pm
@@ -101,6 +101,7 @@ use constant DB_COLUMNS => qw(
visibility_field_id
visibility_value_id
value_field_id
+ reverse_desc
);
use constant REQUIRED_CREATE_FIELDS => qw(name description);
@@ -120,6 +121,7 @@ use constant VALIDATORS => {
use constant UPDATE_VALIDATORS => {
value_field_id => \&_check_value_field_id,
visibility_value_id => \&_check_control_value,
+ reverse_desc => \&_check_reverse_desc,
};
use constant UPDATE_COLUMNS => qw(
@@ -132,6 +134,7 @@ use constant UPDATE_COLUMNS => qw(
visibility_field_id
visibility_value_id
value_field_id
+ reverse_desc
type
);
@@ -357,6 +360,22 @@ sub _check_control_value {
return $value_obj->id;
}
+sub _check_reverse_desc {
+ my ($invocant, $reverse_desc, $type) = @_;
+
+ if (blessed $invocant) {
+ $type = $invocant->type;
+ }
+
+ if ($type != FIELD_TYPE_BUG_ID) {
+ return undef; # store NULL for non-reversible field types
+ }
+
+ $reverse_desc = clean_text($reverse_desc);
+ return $reverse_desc;
+}
+
+
=pod
=head2 Instance Properties
@@ -637,6 +656,44 @@ sub controls_values_of {
return $self->{controls_values_of};
}
+=over
+
+=item C<is_relationship>
+
+Applies only to fields of type FIELD_TYPE_BUG_ID.
+Checks to see if a reverse relationship description has been set.
+This is the canonical condition to enable reverse link display,
+dependency tree display, and similar functionality.
+
+=back
+
+=cut
+
+sub is_relationship {
+ my $self = shift;
+ my $desc = $self->reverse_desc;
+ if (defined $desc && $desc ne "") {
+ return 1;
+ }
+ return 0;
+}
+
+=over
+
+=item C<reverse_desc>
+
+Applies only to fields of type FIELD_TYPE_BUG_ID.
+Describes the reverse relationship of this field.
+For example, if a BUG_ID field is called "Is a duplicate of",
+the reverse description would be "Duplicates of this bug".
+
+=back
+
+=cut
+
+sub reverse_desc { return $_[0]->{reverse_desc} }
+
+
=pod
=head2 Instance Mutators
@@ -661,6 +718,8 @@ They will throw an error if you try to set the values to something invalid.
=item C<set_buglist>
+=item C<set_reverse_desc>
+
=item C<set_visibility_field>
=item C<set_visibility_value>
@@ -677,6 +736,7 @@ sub set_obsolete { $_[0]->set('obsolete', $_[1]); }
sub set_sortkey { $_[0]->set('sortkey', $_[1]); }
sub set_in_new_bugmail { $_[0]->set('mailhead', $_[1]); }
sub set_buglist { $_[0]->set('buglist', $_[1]); }
+sub set_reverse_desc { $_[0]->set('reverse_desc', $_[1]); }
sub set_visibility_field {
my ($self, $value) = @_;
$self->set('visibility_field_id', $value);
@@ -868,6 +928,12 @@ sub run_create_validators {
$class->_check_value_field_id($params->{value_field_id},
($type == FIELD_TYPE_SINGLE_SELECT
|| $type == FIELD_TYPE_MULTI_SELECT) ? 1 : 0);
+
+ $params->{reverse_desc} = $class->_check_reverse_desc(
+ $params->{reverse_desc}, $type);
+
+
+
return $params;
}
diff --git a/Bugzilla/Install/DB.pm b/Bugzilla/Install/DB.pm
index f6d6edcb1..d150a4e9b 100644
--- a/Bugzilla/Install/DB.pm
+++ b/Bugzilla/Install/DB.pm
@@ -102,6 +102,9 @@ sub update_fielddefs_definition {
$dbh->do('UPDATE fielddefs SET buglist = 1 WHERE custom = 1 AND type != ' . FIELD_TYPE_MULTI_SELECT);
}
+ #2008-08-26 elliotte_martin@yahoo.com - Bug 251556
+ $dbh->bz_add_column('fielddefs', 'reverse_desc', {TYPE => 'TINYTEXT'});
+
# Remember, this is not the function for adding general table changes.
# That is below. Add new changes to the fielddefs table above this