[Rt-commit] rt branch, 4.0/columnmap-cache-cf, created. rt-4.0.6-169-geba80a2

Alex Vandiver alexmv at bestpractical.com
Wed Oct 24 01:12:51 EDT 2012


The branch, 4.0/columnmap-cache-cf has been created
        at  eba80a245e237ff10ccf75cc7eefa4a8a7d6ab7a (commit)

- Log -----------------------------------------------------------------
commit dda0fa00bb70334a770d2cc35f012bad2ff61eba
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Tue Jun 12 13:57:27 2012 -0400

    RT::ObjectCustomFieldValues calls LimitToEnabled by default
    
    This cleans up an unnecessary (Disabled = 0 OR Disabled = 0)

diff --git a/lib/RT/CustomField.pm b/lib/RT/CustomField.pm
index 2002d4e..d065b7f 100644
--- a/lib/RT/CustomField.pm
+++ b/lib/RT/CustomField.pm
@@ -1656,7 +1656,6 @@ sub ValuesForObject {
     
     
     $values->LimitToCustomField($self->Id);
-    $values->LimitToEnabled();
     $values->LimitToObject($object);
 
     return ($values);

commit ce698ecd6bb2c5198442e2ca65cbbb84ad12e764
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Tue Jun 12 16:30:27 2012 -0400

    Move "global or queue" logic to LoadCustomFieldByIdentifier
    
    The logic for attempting to load a queue-specific queue, and then the
    global one, was on the CustomFieldValues method.  Move the logic to
    LoadCustomFieldByIdentifier, which is called by
    RT::Record->CustomFieldValues, rather than overriding CustomFieldValues
    directly; this allows other methods to simple call
    ->LoadCustomFieldByIdentifier and gain the queue-or-global
    functionality.
    
    This change also causes ->CustomFieldValues (and thus both
    ->FirstCustomFieldValue and ->CustomFieldValuesAsString), when called on
    tickets with an invalid CF name, to warn.  This makes it consistent with
    ->CustomFieldValues called on other types of objects, and may provide
    useful feedback when a CF name is improperly specified.

diff --git a/lib/RT/Ticket.pm b/lib/RT/Ticket.pm
index c6a5e5b..e4c5384 100644
--- a/lib/RT/Ticket.pm
+++ b/lib/RT/Ticket.pm
@@ -3666,37 +3666,29 @@ sub TransactionCustomFields {
 }
 
 
+=head2 LoadCustomFieldByIdentifier
 
-=head2 CustomFieldValues
-
-# Do name => id mapping (if needed) before falling back to
-# RT::Record's CustomFieldValues
-
-See L<RT::Record>
+Finds and returns the custom field of the given name for the ticket,
+overriding L<RT::Record/LoadCustomFieldByIdentifier> to look for
+queue-specific CFs before global ones.
 
 =cut
 
-sub CustomFieldValues {
+sub LoadCustomFieldByIdentifier {
     my $self  = shift;
     my $field = shift;
 
-    return $self->SUPER::CustomFieldValues( $field ) if !$field || $field =~ /^\d+$/;
+    return $self->SUPER::LoadCustomFieldByIdentifier($field)
+        if ref $field or $field =~ /^\d+$/;
 
     my $cf = RT::CustomField->new( $self->CurrentUser );
     $cf->SetContextObject( $self );
     $cf->LoadByNameAndQueue( Name => $field, Queue => $self->Queue );
-    unless ( $cf->id ) {
-        $cf->LoadByNameAndQueue( Name => $field, Queue => 0 );
-    }
-
-    # If we didn't find a valid cfid, give up.
-    return RT::ObjectCustomFieldValues->new( $self->CurrentUser ) unless $cf->id;
-
-    return $self->SUPER::CustomFieldValues( $cf->id );
+    $cf->LoadByNameAndQueue( Name => $field, Queue => 0 ) unless $cf->id;
+    return $cf;
 }
 
 
-
 =head2 CustomFieldLookupType
 
 Returns the RT::Ticket lookup type, which can be passed to 
diff --git a/lib/RT/Transaction.pm b/lib/RT/Transaction.pm
index 5b3641f..fa2c56f 100644
--- a/lib/RT/Transaction.pm
+++ b/lib/RT/Transaction.pm
@@ -1175,37 +1175,31 @@ sub UpdateCustomFields {
     }
 }
 
+=head2 LoadCustomFieldByIdentifier
 
-
-=head2 CustomFieldValues
-
- Do name => id mapping (if needed) before falling back to RT::Record's CustomFieldValues
-
- See L<RT::Record>
+Finds and returns the custom field of the given name for the
+transaction, overriding L<RT::Record/LoadCustomFieldByIdentifier> to
+look for queue-specific CFs before global ones.
 
 =cut
 
-sub CustomFieldValues {
+sub LoadCustomFieldByIdentifier {
     my $self  = shift;
     my $field = shift;
 
-    if ( UNIVERSAL::can( $self->Object, 'QueueObj' ) ) {
-
-        # XXX: $field could be undef when we want fetch values for all CFs
-        #      do we want to cover this situation somehow here?
-        unless ( defined $field && $field =~ /^\d+$/o ) {
-            my $CFs = RT::CustomFields->new( $self->CurrentUser );
-            $CFs->SetContextObject( $self->Object );
-            $CFs->Limit( FIELD => 'Name', VALUE => $field );
-            $CFs->LimitToLookupType($self->CustomFieldLookupType);
-            $CFs->LimitToGlobalOrObjectId($self->Object->QueueObj->id);
-            $field = $CFs->First->id if $CFs->First;
-        }
-    }
-    return $self->SUPER::CustomFieldValues($field);
-}
+    return $self->SUPER::LoadCustomFieldByIdentifier($field)
+        if ref $field or $field =~ /^\d+$/;
 
+    return $self->SUPER::LoadCustomFieldByIdentifier($field)
+        unless UNIVERSAL::can( $self->Object, 'QueueObj' );
 
+    my $CFs = RT::CustomFields->new( $self->CurrentUser );
+    $CFs->SetContextObject( $self->Object );
+    $CFs->Limit( FIELD => 'Name', VALUE => $field );
+    $CFs->LimitToLookupType($self->CustomFieldLookupType);
+    $CFs->LimitToGlobalOrObjectId($self->Object->QueueObj->id);
+    return $CFs->First || RT::CustomField->new( $self->CurrentUser );
+}
 
 =head2 CustomFieldLookupType
 
diff --git a/t/customfields/api.t b/t/customfields/api.t
index d739a57..228693f 100644
--- a/t/customfields/api.t
+++ b/t/customfields/api.t
@@ -3,7 +3,8 @@
 use strict;
 use warnings FATAL => 'all';
 
-use RT::Test nodata => 1, tests => 139;
+use RT::Test nodata => 1, tests => 145;
+use Test::Warn;
 
 # Before we get going, ditch all object_cfs; this will remove 
 # all custom fields systemwide;
@@ -69,13 +70,21 @@ is( $cfvs->Count, 0 );
 is( $ticket->FirstCustomFieldValue, undef );
 
 # CF with ID -1 shouldnt exist at all
-$cfvs = $ticket->CustomFieldValues( -1 );
+warning_like {
+    $cfvs = $ticket->CustomFieldValues( -1 );
+} qr{Couldn't load custom field};
 is( $cfvs->Count, 0 );
-is( $ticket->FirstCustomFieldValue( -1 ), undef );
+warning_like {
+    is( $ticket->FirstCustomFieldValue( -1 ), undef );
+} qr{Couldn't load custom field};
 
-$cfvs = $ticket->CustomFieldValues( 'SomeUnexpedCustomFieldName' );
+warning_like {
+    $cfvs = $ticket->CustomFieldValues( 'SomeUnexpedCustomFieldName' );
+} qr{Couldn't load custom field};
 is( $cfvs->Count, 0 );
-is( $ticket->FirstCustomFieldValue( 'SomeUnexpedCustomFieldName' ), undef );
+warning_like {
+    is( $ticket->FirstCustomFieldValue( 'SomeUnexpedCustomFieldName' ), undef );
+} qr{Couldn't load custom field};
 
 for (@custom_fields) {
 	$cfvs = $ticket->CustomFieldValues( $_->id );
@@ -183,9 +192,13 @@ $test_add_delete_cycle->( sub { return $_[0] } );
 $ticket->AddCustomFieldValue( Field => $local_cf2->id , Value => 'Baz' );
 $ticket->AddCustomFieldValue( Field => $global_cf3->id , Value => 'Baz' );
 # now if we ask for cf values on RecordCustomFields4 we should not get any
-$cfvs = $ticket->CustomFieldValues( 'RecordCustomFields4' );
+warning_like {
+    $cfvs = $ticket->CustomFieldValues( 'RecordCustomFields4' );
+} qr{Couldn't load custom field};
 is( $cfvs->Count, 0, "No custom field values for non-Queue cf" );
-is( $ticket->FirstCustomFieldValue( 'RecordCustomFields4' ), undef, "No first custom field value for non-Queue cf" );
+warning_like {
+    is( $ticket->FirstCustomFieldValue( 'RecordCustomFields4' ), undef, "No first custom field value for non-Queue cf" );
+} qr{Couldn't load custom field};
 
 {
     my $cfname = $global_cf3->Name;

commit eba80a245e237ff10ccf75cc7eefa4a8a7d6ab7a
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Tue Jun 12 16:41:38 2012 -0400

    Cache CFs in ColumnMap on a per-request basis
    
    When displaying /n/ rows of search results with /m/ columns of global CF
    values displayed, custom field queries accounted for /n/ * /m/ * 3
    queries; one to try to load the queue-specific CF with the column name,
    one to load the global CF with that name, and one to load the OCFV for
    that CF and ticket.  With sufficient CFs in a search result format,
    these account for a significant performance impact, despite being
    relatively well-indexed.
    
    Cache the CF objects in the per-request $m->notes() cache to eliminate
    the CF loads, which account for ½ to ⅔ of those queries, depending on
    the prevalence of global CFs.  The cache key must also include the queue
    name -- or class, in the case of article CFs -- as a single search may
    include results from multiple queues, each of which may resolve a CF
    name differently.

diff --git a/lib/RT/Article.pm b/lib/RT/Article.pm
index 24b952a..122624c 100644
--- a/lib/RT/Article.pm
+++ b/lib/RT/Article.pm
@@ -611,6 +611,20 @@ sub CustomFieldLookupType {
     "RT::Class-RT::Article";
 }
 
+=head2 CustomFieldAppliedTo
+
+Returns the tuple of $ocf->CustomField->RecordClassFromLookupType and
+$ocf->ObjectId which all custom fields observed on this object will
+have, invariently.  For articles, this is C<RT::Class> and the article's
+class' id.
+
+=cut
+
+sub CustomFieldAppliedTo {
+    my $self = shift;
+    return ("RT::Class", $self->Class);
+}
+
 # _LookupId is the id of the toplevel type object the customfield is joined to
 # in this case, that's an RT::Class.
 
diff --git a/lib/RT/Queue.pm b/lib/RT/Queue.pm
index 406df92..0cddcce 100644
--- a/lib/RT/Queue.pm
+++ b/lib/RT/Queue.pm
@@ -701,6 +701,21 @@ sub TicketTransactionCustomFields {
 }
 
 
+=head2 CustomFieldAppliedTo
+
+Returns the tuple of $ocf->CustomField->RecordClassFromLookupType and
+$ocf->ObjectId which all custom fields observed on this object will
+have, invariently.  For queues, this is C<RT::Queue> and the object's
+own id.
+
+=cut
+
+sub CustomFieldAppliedTo {
+    my $self = shift;
+    return ("RT::Queue", $self->Id);
+}
+
+
 
 
 
diff --git a/lib/RT/Ticket.pm b/lib/RT/Ticket.pm
index e4c5384..29e6f1c 100644
--- a/lib/RT/Ticket.pm
+++ b/lib/RT/Ticket.pm
@@ -3701,6 +3701,21 @@ sub CustomFieldLookupType {
     "RT::Queue-RT::Ticket";
 }
 
+=head2 CustomFieldAppliedTo
+
+Returns the tuple of $ocf->CustomField->RecordClassFromLookupType and
+$ocf->ObjectId which all custom fields observed on this object will
+have, invariently.  For tickets, this is C<RT::Queue> and the ticket's
+queue id.
+
+=cut
+
+sub CustomFieldAppliedTo {
+    my $self = shift;
+    return ("RT::Queue", $self->Queue);
+}
+
+
 =head2 ACLEquivalenceObjects
 
 This method returns a list of objects for which a user's rights also apply
diff --git a/lib/RT/Transaction.pm b/lib/RT/Transaction.pm
index fa2c56f..ab8b48d 100644
--- a/lib/RT/Transaction.pm
+++ b/lib/RT/Transaction.pm
@@ -1213,6 +1213,20 @@ sub CustomFieldLookupType {
     "RT::Queue-RT::Ticket-RT::Transaction";
 }
 
+=head2 CustomFieldAppliedTo
+
+Returns the tuple of $ocf->CustomField->RecordClassFromLookupType and
+$ocf->ObjectId which all custom fields observed on this object will
+have, invariently.  For transactions, this is C<RT::Queue> and the
+transaction's ticket's queue id.
+
+=cut
+
+sub CustomFieldAppliedTo {
+    my $self = shift;
+    return ($self->Object->CustomFieldAppliedTo);
+}
+
 
 =head2 SquelchMailTo
 
diff --git a/share/html/Elements/ColumnMap b/share/html/Elements/ColumnMap
index 87fd61b..48ec2ad 100644
--- a/share/html/Elements/ColumnMap
+++ b/share/html/Elements/ColumnMap
@@ -96,13 +96,24 @@ my $COLUMN_MAP = {
         attribute => sub { return shift @_ },
         title     => sub { return pop @_ },
         value     => sub {
+            # Cache the CF object on a per-request basis, to avoid
+            # having to load it for every row
+            my $key = "CF--$_[-1]";
+            $key = join("-","CF",$_[0]->CustomFieldAppliedTo,$_[-1])
+                if $_[0]->can("CustomFieldAppliedTo");
+
+            my $cf = $m->notes($key);
+            unless ($cf) {
+                $cf = $_[0]->LoadCustomFieldByIdentifier($_[-1]);
+                $m->notes($key, $cf);
+            }
+
             # Display custom field contents, separated by newlines.
             # For Image custom fields we also show a thumbnail here.
-
-            my $values = $_[0]->CustomFieldValues( $_[-1] );
+            my $values = $cf->ValuesForObject( $_[0] );
             my @values = map {
                 (
-                    ($_->CustomFieldObj->Type eq 'Image')
+                    ($cf->Type eq 'Image')
                         ? \($m->scomp( '/Elements/ShowCustomFieldImage', Object => $_ ))
                         : $_->Content
                 ),

-----------------------------------------------------------------------


More information about the Rt-commit mailing list