rt 4.2.16
[freeside.git] / rt / lib / RT / ObjectCustomFieldValue.pm
index 0e63ced..9b699c4 100644 (file)
@@ -2,7 +2,7 @@
 #
 # COPYRIGHT:
 #
-# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2019 Best Practical Solutions, LLC
 #                                          <sales@bestpractical.com>
 #
 # (Except where explicitly superseded by other copyright notices)
@@ -50,6 +50,7 @@ package RT::ObjectCustomFieldValue;
 
 use strict;
 use warnings;
+use base 'RT::Record';
 
 use RT::Interface::Web;
 use Regexp::Common qw(RE_net_IPv4);
@@ -60,10 +61,7 @@ require Net::CIDR;
 # Allow the empty IPv6 address
 $IPv6_re = qr/(?:$IPv6_re|::)/;
 
-
-
 use RT::CustomField;
-use base 'RT::Record';
 
 sub Table {'ObjectCustomFieldValues'}
 
@@ -90,13 +88,17 @@ sub Create {
     my ($val, $msg) = $cf->_CanonicalizeValue(\%args);
     return ($val, $msg) unless $val;
 
-    if ( defined $args{'Content'} && length( Encode::encode_utf8($args{'Content'}) ) > 255 ) {
+    my $encoded = Encode::encode("UTF-8", $args{'Content'});
+    if ( defined $args{'Content'} && length( $encoded ) > 255 ) {
         if ( defined $args{'LargeContent'} && length $args{'LargeContent'} ) {
             $RT::Logger->error("Content is longer than 255 bytes and LargeContent specified");
         }
         else {
-            $args{'LargeContent'} = $args{'Content'};
-            $args{'Content'} = '';
+            # _EncodeLOB, and thus LargeContent, takes bytes; Content is
+            # in characters.  Encode it; this may replace illegal
+            # codepoints (e.g. \x{FDD0}) with \x{FFFD}.
+            $args{'LargeContent'} = Encode::encode("UTF-8",$args{'Content'});
+            $args{'Content'} = undef;
             $args{'ContentType'} ||= 'text/plain';
         }
     }
@@ -105,7 +107,7 @@ sub Create {
         $self->_EncodeLOB( $args{'LargeContent'}, $args{'ContentType'} )
             if defined $args{'LargeContent'};
 
-    return $self->SUPER::Create(
+    ( my $id, $msg ) = $self->SUPER::Create(
         CustomField     => $args{'CustomField'},
         ObjectType      => $args{'ObjectType'},
         ObjectId        => $args{'ObjectId'},
@@ -115,6 +117,23 @@ sub Create {
         ContentType     => $args{'ContentType'},
         ContentEncoding => $args{'ContentEncoding'},
     );
+
+    if ( $id ) {
+        my $new_value = RT::ObjectCustomFieldValue->new( $self->CurrentUser );
+        $new_value->Load( $id );
+        my $ocfv_key = $new_value->GetOCFVCacheKey();
+        if ( $RT::ObjectCustomFieldValues::_OCFV_CACHE->{$ocfv_key} ) {
+            push @{ $RT::ObjectCustomFieldValues::_OCFV_CACHE->{$ocfv_key} },
+              {
+                'ObjectId'       => $new_value->Id,
+                'CustomFieldObj' => $new_value->CustomFieldObj,
+                'Content'        => $new_value->_Value('Content'),
+                'LargeContent'   => $new_value->LargeContent,
+              };
+        }
+    }
+
+    return wantarray ? ( $id, $msg ) : $id;
 }
 
 
@@ -286,7 +305,15 @@ Disable this value. Used to remove "current" values from records while leaving t
 
 sub Delete {
     my $self = shift;
-    return $self->SetDisabled(1);
+    my ( $ret, $msg ) = $self->SetDisabled( 1 );
+    if ( $ret ) {
+        my $ocfv_key = $self->GetOCFVCacheKey();
+        if ( $RT::ObjectCustomFieldValues::_OCFV_CACHE->{$ocfv_key} ) {
+            @{ $RT::ObjectCustomFieldValues::_OCFV_CACHE->{$ocfv_key} } =
+              grep { $_->{'ObjectId'} != $self->Id } @{ $RT::ObjectCustomFieldValues::_OCFV_CACHE->{$ocfv_key} };
+        }
+    }
+    return wantarray ? ( $ret, $msg ) : $ret;
 }
 
 =head2 _FillInTemplateURL URL
@@ -479,6 +506,20 @@ sub ParseIP {
 }
 
 
+=head2 GetOCFVCacheKey
+
+Get the OCFV cache key for this object
+
+=cut
+
+sub GetOCFVCacheKey {
+    my $self = shift;
+    my $ocfv_key = "CustomField-" . $self->CustomField
+        . '-ObjectType-' . $self->ObjectType
+        . '-ObjectId-' . $self->ObjectId;
+    return $ocfv_key;
+}
+
 =head2 id
 
 Returns the current value of id.
@@ -690,37 +731,47 @@ sub _CoreAccessible {
     {
 
         id =>
-               {read => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => ''},
+                {read => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => ''},
         CustomField =>
-               {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => ''},
+                {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => ''},
         ObjectType =>
-               {read => 1, write => 1, sql_type => 12, length => 255,  is_blob => 0,  is_numeric => 0,  type => 'varchar(255)', default => ''},
+                {read => 1, write => 1, sql_type => 12, length => 255,  is_blob => 0,  is_numeric => 0,  type => 'varchar(255)', default => ''},
         ObjectId =>
-               {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => ''},
+                {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => ''},
         SortOrder =>
-               {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
+                {read => 1, write => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
         Content =>
-               {read => 1, write => 1, sql_type => 12, length => 255,  is_blob => 0,  is_numeric => 0,  type => 'varchar(255)', default => ''},
+                {read => 1, write => 1, sql_type => 12, length => 255,  is_blob => 0,  is_numeric => 0,  type => 'varchar(255)', default => ''},
         LargeContent =>
-               {read => 1, write => 1, sql_type => -4, length => 0,  is_blob => 1,  is_numeric => 0,  type => 'longblob', default => ''},
+                {read => 1, write => 1, sql_type => -4, length => 0,  is_blob => 1,  is_numeric => 0,  type => 'longblob', default => ''},
         ContentType =>
-               {read => 1, write => 1, sql_type => 12, length => 80,  is_blob => 0,  is_numeric => 0,  type => 'varchar(80)', default => ''},
+                {read => 1, write => 1, sql_type => 12, length => 80,  is_blob => 0,  is_numeric => 0,  type => 'varchar(80)', default => ''},
         ContentEncoding =>
-               {read => 1, write => 1, sql_type => 12, length => 80,  is_blob => 0,  is_numeric => 0,  type => 'varchar(80)', default => ''},
+                {read => 1, write => 1, sql_type => 12, length => 80,  is_blob => 0,  is_numeric => 0,  type => 'varchar(80)', default => ''},
         Creator =>
-               {read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
+                {read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
         Created =>
-               {read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
+                {read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
         LastUpdatedBy =>
-               {read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
+                {read => 1, auto => 1, sql_type => 4, length => 11,  is_blob => 0,  is_numeric => 1,  type => 'int(11)', default => '0'},
         LastUpdated =>
-               {read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
+                {read => 1, auto => 1, sql_type => 11, length => 0,  is_blob => 0,  is_numeric => 0,  type => 'datetime', default => ''},
         Disabled =>
-               {read => 1, write => 1, sql_type => 5, length => 6,  is_blob => 0,  is_numeric => 1,  type => 'smallint(6)', default => '0'},
+                {read => 1, write => 1, sql_type => 5, length => 6,  is_blob => 0,  is_numeric => 1,  type => 'smallint(6)', default => '0'},
 
  }
 };
 
+sub FindDependencies {
+    my $self = shift;
+    my ($walker, $deps) = @_;
+
+    $self->SUPER::FindDependencies($walker, $deps);
+
+    $deps->Add( out => $self->CustomFieldObj );
+    $deps->Add( out => $self->Object );
+}
+
 RT::Base->_ImportOverlays();
 
 1;