summaryrefslogtreecommitdiffstats
path: root/Bugzilla/Object.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Bugzilla/Object.pm')
-rw-r--r--Bugzilla/Object.pm59
1 files changed, 56 insertions, 3 deletions
diff --git a/Bugzilla/Object.pm b/Bugzilla/Object.pm
index d4574abd2..34134a69f 100644
--- a/Bugzilla/Object.pm
+++ b/Bugzilla/Object.pm
@@ -61,6 +61,9 @@ sub new {
my $class = ref($invocant) || $invocant;
my $object = $class->_init(@_);
bless($object, $class) if $object;
+
+ Bugzilla::Hook::process('object_end_of_new', { object => $object });
+
return $object;
}
@@ -72,6 +75,8 @@ sub new {
sub _init {
my $class = shift;
my ($param) = @_;
+ my $object = $class->_cache_get($param);
+ return $object if $object;
my $dbh = Bugzilla->dbh;
my $columns = join(',', $class->_get_db_columns);
my $table = $class->DB_TABLE;
@@ -82,7 +87,6 @@ sub _init {
if (ref $param eq 'HASH') {
$id = $param->{id};
}
- my $object;
if (defined $id) {
# We special-case if somebody specifies an ID, so that we can
@@ -125,9 +129,48 @@ sub _init {
"SELECT $columns FROM $table WHERE $condition", undef, @values);
}
+ $class->_cache_set($param, $object) if $object;
return $object;
}
+# Provides a mechanism for objects to be cached in the request_cahce
+
+sub _cache_get {
+ my $class = shift;
+ my ($param) = @_;
+ my $cache_key = $class->cache_key($param)
+ || return;
+ return Bugzilla->request_cache->{$cache_key};
+}
+
+sub _cache_set {
+ my $class = shift;
+ my ($param, $object) = @_;
+ my $cache_key = $class->cache_key($param)
+ || return;
+ Bugzilla->request_cache->{$cache_key} = $object;
+}
+
+sub _cache_remove {
+ my $class = shift;
+ my ($param, $object) = @_;
+ $param->{cache} = 1;
+ my $cache_key = $class->cache_key($param)
+ || return;
+ delete Bugzilla->request_cache->{$cache_key};
+}
+
+sub cache_key {
+ my $class = shift;
+ my ($param) = @_;
+ if (ref($param) && $param->{cache} && ($param->{id} || $param->{name})) {
+ $class = blessed($class) if blessed($class);
+ return $class . ',' . ($param->{id} || $param->{name});
+ } else {
+ return;
+ }
+}
+
sub check {
my ($invocant, $param) = @_;
my $class = ref($invocant) || $invocant;
@@ -228,8 +271,11 @@ sub match {
}
next;
}
-
- $class->_check_field($field, 'match');
+
+ # It's always safe to use the field defined by classes as being
+ # their ID field. In particular, this means that new_from_list()
+ # is exempted from this check.
+ $class->_check_field($field, 'match') unless $field eq $class->ID_FIELD;
if (ref $value eq 'ARRAY') {
# IN () is invalid SQL, and if we have an empty list
@@ -332,12 +378,17 @@ sub set_all {
my %field_values = %$params;
my @sorted_names = $self->_sort_by_dep(keys %field_values);
+
foreach my $key (@sorted_names) {
# It's possible for one set_ method to delete a key from $params
# for another set method, so if that's happened, we don't call the
# other set method.
next if !exists $field_values{$key};
my $method = "set_$key";
+ if (!$self->can($method)) {
+ my $class = ref($self) || $self;
+ ThrowCodeError("unknown_method", { method => "${class}::${method}" });
+ }
$self->$method($field_values{$key}, \%field_values);
}
Bugzilla::Hook::process('object_end_of_set_all',
@@ -398,6 +449,7 @@ sub update {
$self->audit_log(\%changes) if $self->AUDIT_UPDATES;
$dbh->bz_commit_transaction();
+ $self->_cache_remove({ id => $self->id });
if (wantarray) {
return (\%changes, $old_self);
@@ -416,6 +468,7 @@ sub remove_from_db {
$self->audit_log(AUDIT_REMOVE) if $self->AUDIT_REMOVES;
$dbh->do("DELETE FROM $table WHERE $id_field = ?", undef, $self->id);
$dbh->bz_commit_transaction();
+ $self->_cache_remove({ id => $self->id });
undef $self;
}