From 49cf9cce67f65fe53fcd950e2ba848ebf0a87ba5 Mon Sep 17 00:00:00 2001 From: Max Kanat-Alexander Date: Fri, 1 Oct 2010 04:27:21 -0700 Subject: Bug 600123 - Eliminate Bugzilla::Bug's AUTOLOAD r=glob, a=mkanat --- Bugzilla/Bug.pm | 153 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 89 insertions(+), 64 deletions(-) (limited to 'Bugzilla/Bug.pm') diff --git a/Bugzilla/Bug.pm b/Bugzilla/Bug.pm index 1e2b78c9a..fccf94a02 100644 --- a/Bugzilla/Bug.pm +++ b/Bugzilla/Bug.pm @@ -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; -- cgit v1.2.3-24-g4f1b