Commit 49cf9cce authored by Max Kanat-Alexander's avatar Max Kanat-Alexander

Bug 600123 - Eliminate Bugzilla::Bug's AUTOLOAD

r=glob, a=mkanat
parent 96d709ed
......@@ -309,11 +309,21 @@ use constant EXTRA_REQUIRED_FIELDS => qw(target_milestone cc qa_contact groups);
#####################################################################
# This and "new" catch every single way of creating a bug, so that we
# can call _create_cf_accessors.
sub _do_list_select {
my $invocant = shift;
$invocant->_create_cf_accessors();
return $invocant->SUPER::_do_list_select(@_);
}
sub new {
my $invocant = shift;
my $class = ref($invocant) || $invocant;
my $param = shift;
$class->_create_cf_accessors();
# Remove leading "#" mark if we've just been passed an id.
if (!ref $param && $param =~ /^#(\d+)$/) {
$param = $1;
......@@ -2977,9 +2987,45 @@ sub remove_see_also {
}
#####################################################################
# Instance Accessors
# Simple Accessors
#####################################################################
# These are accessors that don't need to access the database.
# Keep them in alphabetical order.
sub alias { return $_[0]->{alias} }
sub bug_file_loc { return $_[0]->{bug_file_loc} }
sub bug_id { return $_[0]->{bug_id} }
sub bug_severity { return $_[0]->{bug_severity} }
sub bug_status { return $_[0]->{bug_status} }
sub cclist_accessible { return $_[0]->{cclist_accessible} }
sub component_id { return $_[0]->{component_id} }
sub creation_ts { return $_[0]->{creation_ts} }
sub estimated_time { return $_[0]->{estimated_time} }
sub deadline { return $_[0]->{deadline} }
sub delta_ts { return $_[0]->{delta_ts} }
sub error { return $_[0]->{error} }
sub everconfirmed { return $_[0]->{everconfirmed} }
sub lastdiffed { return $_[0]->{lastdiffed} }
sub op_sys { return $_[0]->{op_sys} }
sub priority { return $_[0]->{priority} }
sub product_id { return $_[0]->{product_id} }
sub remaining_time { return $_[0]->{remaining_time} }
sub reporter_accessible { return $_[0]->{reporter_accessible} }
sub rep_platform { return $_[0]->{rep_platform} }
sub resolution { return $_[0]->{resolution} }
sub short_desc { return $_[0]->{short_desc} }
sub status_whiteboard { return $_[0]->{status_whiteboard} }
sub target_milestone { return $_[0]->{target_milestone} }
sub version { return $_[0]->{version} }
#####################################################################
# Complex Accessors
#####################################################################
# These are accessors that have to access the database for additional
# information about a bug.
# These subs are in alphabetical order, as much as possible.
# If you add a new sub, please try to keep it in alphabetical order
# with the other ones.
......@@ -3099,9 +3145,6 @@ sub blocked {
return $self->{'blocked'};
}
# Even bugs in an error state always have a bug_id.
sub bug_id { $_[0]->{'bug_id'}; }
sub bug_group {
my ($self) = @_;
return join(', ', (map { $_->name } @{$self->groups_in}));
......@@ -4046,73 +4089,55 @@ sub ValidateDependencies {
#####################################################################
# Autoloaded Accessors
# Custom Field Accessors
#####################################################################
# Determines whether an attribute access trapped by the AUTOLOAD function
# is for a valid bug attribute. Bug attributes are properties and methods
# predefined by this module as well as bug fields for which an accessor
# can be defined by AUTOLOAD at runtime when the accessor is first accessed.
#
# XXX Strangely, some predefined attributes are on the list, but others aren't,
# and the original code didn't specify why that is. Presumably the only
# attributes that need to be on this list are those that aren't predefined;
# we should verify that and update the list accordingly.
#
sub _validate_attribute {
my ($attribute) = @_;
my @valid_attributes = (
# Miscellaneous properties and methods.
qw(error groups product_id component_id
comments milestoneurl attachments isopened
flag_types num_attachment_flag_types
show_attachment_flags any_flags_requesteeble
lastdiffed),
# Bug fields.
Bugzilla::Bug->fields
);
return grep($attribute eq $_, @valid_attributes) ? 1 : 0;
}
sub AUTOLOAD {
use vars qw($AUTOLOAD);
my $attr = $AUTOLOAD;
$attr =~ s/.*:://;
return unless $attr=~ /[^A-Z]/;
if (!_validate_attribute($attr)) {
require Carp;
Carp::confess("invalid bug attribute $attr");
}
no strict 'refs';
*$AUTOLOAD = sub {
my $self = shift;
return $self->{$attr} if defined $self->{$attr};
sub _create_cf_accessors {
my ($invocant) = @_;
my $class = ref($invocant) || $invocant;
return if Bugzilla->request_cache->{"${class}_cf_accessors_created"};
$self->{_multi_selects} ||= Bugzilla->fields(
{ custom => 1, type => FIELD_TYPE_MULTI_SELECT });
my $fields = Bugzilla->fields({ custom => 1 });
foreach my $field (@$fields) {
my $accessor = $class->_accessor_for($field);
my $name = "${class}::" . $field->name;
{
no strict 'refs';
next if defined *{$name};
*{$name} = $accessor;
}
}
if ( grep($_->name eq $attr, @{$self->{_multi_selects}}) ) {
# There is a bug in Perl 5.10.0, which is fixed in 5.10.1,
# which taints $attr at this point. trick_taint() can go
# away once we require 5.10.1 or newer.
trick_taint($attr);
Bugzilla->request_cache->{"${class}_cf_accessors_created"} = 1;
}
$self->{$attr} ||= Bugzilla->dbh->selectcol_arrayref(
"SELECT value FROM bug_$attr WHERE bug_id = ? ORDER BY value",
undef, $self->id);
return $self->{$attr};
}
sub _accessor_for {
my ($class, $field) = @_;
if ($field->type == FIELD_TYPE_MULTI_SELECT) {
return $class->_multi_select_accessor($field->name);
}
return $class->_cf_accessor($field->name);
}
return '';
};
sub _cf_accessor {
my ($class, $field) = @_;
my $accessor = sub {
my ($self) = @_;
return $self->{$field};
};
return $accessor;
}
goto &$AUTOLOAD;
sub _multi_select_accessor {
my ($class, $field) = @_;
my $accessor = sub {
my ($self) = @_;
$self->{$field} ||= Bugzilla->dbh->selectcol_arrayref(
"SELECT value FROM bug_$field WHERE bug_id = ? ORDER BY value",
undef, $self->id);
return $self->{$field};
};
return $accessor;
}
1;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment