summaryrefslogtreecommitdiff
path: root/rt/lib/RT/Record.pm
diff options
context:
space:
mode:
Diffstat (limited to 'rt/lib/RT/Record.pm')
-rwxr-xr-xrt/lib/RT/Record.pm644
1 files changed, 23 insertions, 621 deletions
diff --git a/rt/lib/RT/Record.pm b/rt/lib/RT/Record.pm
index d3a826808..57a5ea7fc 100755
--- a/rt/lib/RT/Record.pm
+++ b/rt/lib/RT/Record.pm
@@ -1,8 +1,8 @@
-# BEGIN BPS TAGGED BLOCK {{{
+# {{{ BEGIN BPS TAGGED BLOCK
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -42,8 +42,7 @@
# works based on those contributions, and sublicense and distribute
# those contributions and any derivatives thereof.
#
-# END BPS TAGGED BLOCK }}}
-
+# }}} END BPS TAGGED BLOCK
=head1 NAME
RT::Record - Base class for RT record objects
@@ -108,48 +107,6 @@ sub _PrimaryKeys {
# }}}
-=head2 Delete
-
-Delete this record object from the database.
-
-=cut
-
-sub Delete {
- my $self = shift;
- my ($rv) = $self->SUPER::Delete;
- if ($rv) {
- return ($rv, $self->loc("Object deleted"));
- } else {
-
- return(0, $self->loc("Object could not be deleted"))
- }
-}
-
-=head2 ObjectTypeStr
-
-Returns a string which is this object's type. The type is the class,
-without the "RT::" prefix.
-
-=begin testing
-
-my $ticket = RT::Ticket->new($RT::SystemUser);
-my $group = RT::Group->new($RT::SystemUser);
-is($ticket->ObjectTypeStr, 'Ticket', "Ticket returns correct typestring");
-is($group->ObjectTypeStr, 'Group', "Group returns correct typestring");
-
-=end testing
-
-=cut
-
-sub ObjectTypeStr {
- my $self = shift;
- if (ref($self) =~ /^.*::(\w+)$/) {
- return $self->loc($1);
- } else {
- return $self->loc(ref($self));
- }
-}
-
=head2 Attributes
Return this object's attributes as an RT::Attributes object
@@ -188,9 +145,7 @@ sub AddAttribute {
Description => $args{'Description'},
Content => $args{'Content'} );
-
- # XXX TODO: Why won't RedoSearch work here?
- $self->Attributes->_DoSearch;
+ $self->Attributes->RedoSearch;
return ($id, $msg);
}
@@ -258,7 +213,7 @@ sub _Handle {
# {{{ sub Create
-=head2 Create PARAMHASH
+=item Create PARAMHASH
Takes a PARAMHASH of Column -> Value pairs.
If any Column has a Validate$PARAMNAME subroutine defined and the
@@ -377,11 +332,10 @@ sub LoadByCols {
$newhash{$key} = $hash{$key};
}
else {
- my ($op, $val, $func);
- ($key, $op, $val, $func) = $self->_Handle->_MakeClauseCaseInsensitive($key, '=', $hash{$key});
+ my ($op, $val);
+ ($key, $op, $val) = $self->_Handle->_MakeClauseCaseInsensitive($key, '=', $hash{$key});
$newhash{$key}->{operator} = $op;
$newhash{$key}->{value} = $val;
- $newhash{$key}->{function} = $func;
}
}
@@ -483,7 +437,6 @@ sub LongSinceUpdateAsString {
# }}} Datehandling
# {{{ sub _Set
-#
sub _Set {
my $self = shift;
@@ -501,33 +454,12 @@ sub _Set {
$args{'Value'} = 0;
}
- my $old_val = $self->__Value($args{'Field'});
- $self->_SetLastUpdated();
- my $ret = $self->SUPER::_Set(
+ $self->_SetLastUpdated();
+ my ( $val, $msg ) = $self->SUPER::_Set(
Field => $args{'Field'},
Value => $args{'Value'},
IsSQL => $args{'IsSQL'}
);
- my ($status, $msg) = $ret->as_array();
-
- # @values has two values, a status code and a message.
-
- # $ret is a Class::ReturnValue object. as such, in a boolean context, it's a bool
- # we want to change the standard "success" message
- if ($status) {
- $msg =
- $self->loc(
- "[_1] changed from [_2] to [_3]",
- $args{'Field'},
- ( $old_val ? "'$old_val'" : $self->loc("(no value)") ),
- '"' . $self->__Value( $args{'Field'}) . '"'
- );
- } else {
-
- $msg = $self->CurrentUser->loc_fuzzy($msg);
- }
- return wantarray ? ($status, $msg) : $ret;
-
}
# }}}
@@ -617,22 +549,8 @@ sub URI {
}
# }}}
+
-=head2 ValidateName NAME
-
-Validate the name of the record we're creating. Mostly, just make sure it's not a numeric ID, which is invalid for Name
-
-=cut
-
-sub ValidateName {
- my $self = shift;
- my $value = shift;
- if ($value && $value=~ /^\d+$/) {
- return(0);
- } else {
- return (1);
- }
-}
@@ -832,26 +750,6 @@ sub _EncodeLOB {
}
-sub _DecodeLOB {
- my $self = shift;
- my $ContentType = shift;
- my $ContentEncoding = shift;
- my $Content = shift;
-
- if ( $ContentEncoding eq 'base64' ) {
- $Content = MIME::Base64::decode_base64($Content);
- }
- elsif ( $ContentEncoding eq 'quoted-printable' ) {
- $Content = MIME::QuotedPrint::decode($Content);
- }
- elsif ( $ContentEncoding && $ContentEncoding ne 'none' ) {
- return ( $self->loc( "Unknown ContentEncoding [_1]", $ContentEncoding ) );
- }
- if ( $ContentType eq 'text/plain' ) {
- $Content = Encode::decode_utf8($Content) unless Encode::is_utf8($Content);
- }
- return ($Content);
-}
# {{{ LINKDIRMAP
# A helper table for links mapping to make it easier
@@ -895,7 +793,8 @@ sub Update {
&& defined(
$ARGSRef->{ $args{'AttributePrefix'} . "-" . $attribute }
)
- ) {
+ )
+ {
$value = $ARGSRef->{ $args{'AttributePrefix'} . "-" . $attribute };
}
@@ -919,15 +818,14 @@ sub Update {
next if ( $value eq $self->$attribute() );
my $method = "Set$attribute";
my ( $code, $msg ) = $self->$method($value);
- my ($prefix) = ref($self) =~ /RT::(\w+)/;
- # Default to $id, but use name if we can get it.
- my $label = $self->id;
- $label = $self->Name if (UNIVERSAL::can($self,'Name'));
- push @results, $self->loc( "$prefix [_1]", $label ) . ': '. $msg;
+ my ($prefix) = ref($self) =~ /RT::(\w+)/;
+ push @results,
+ $self->loc( "$prefix [_1]", $self->id ) . ': '
+ . $self->loc($attribute) . ': '
+ . $self->CurrentUser->loc_fuzzy($msg);
=for loc
-
"[_1] could not be set to [_2].", # loc
"That is already the current value", # loc
"No value sent to _Set!\n", # loc
@@ -940,7 +838,6 @@ sub Update {
"Couldn't find row", # loc
"Missing a primary key?: [_1]", # loc
"Found Object", # loc
-
=cut
}
@@ -948,7 +845,7 @@ sub Update {
return @results;
}
-# {{{ Routines dealing with Links
+# {{{ Routines dealing with Links between tickets
# {{{ Link Collections
@@ -1056,12 +953,6 @@ ok ($addid, $addmsg);
ok (($addid, $addmsg) =$t1->AddLink( Type => 'DependsOn', Target => $t3->id));
ok ($addid, $addmsg);
-my $link = RT::Link->new($RT::SystemUser);
-my ($rv, $msg) = $link->Load($addid);
-ok ($rv, $msg);
-ok ($link->LocalTarget == $t3->id, "Link LocalTarget is correct");
-ok ($link->LocalBase == $t1->id, "Link LocalBase is correct");
-
ok ($t1->HasUnresolvedDependencies, "Ticket ".$t1->Id." has unresolved deps");
ok (!$t1->HasUnresolvedDependencies( Type => 'blah' ), "Ticket ".$t1->Id." has no unresolved blahs");
ok ($t1->HasUnresolvedDependencies( Type => 'approval' ), "Ticket ".$t1->Id." has unresolved approvals");
@@ -1070,12 +961,10 @@ ok (!$t2->HasUnresolvedDependencies, "Ticket ".$t2->Id." has no unresolved deps"
my ($rid, $rmsg)= $t1->Resolve();
ok(!$rid, $rmsg);
-my ($rid2, $rmsg2) = $t2->Resolve();
-ok ($rid2, $rmsg2);
+ok($t2->Resolve);
($rid, $rmsg)= $t1->Resolve();
ok(!$rid, $rmsg);
-my ($rid3,$rmsg3) = $t3->Resolve;
-ok ($rid3,$rmsg3);
+ok($t3->Resolve);
($rid, $rmsg)= $t1->Resolve();
ok($rid, $rmsg);
@@ -1206,14 +1095,6 @@ sub DependsOn {
# {{{ sub _Links
-=head2 Links DIRECTION TYPE
-
-return links to/from this object.
-
-=cut
-
-*Links = \&_Links;
-
sub _Links {
my $self = shift;
@@ -1263,7 +1144,8 @@ sub _AddLink {
my $direction;
if ( $args{'Base'} and $args{'Target'} ) {
- $RT::Logger->debug( "$self tried to create a link. both base and target were specified\n" );
+ $RT::Logger->debug(
+"$self tried to delete a link. both base and target were specified\n" );
return ( 0, $self->loc("Can't specifiy both base and target") );
}
elsif ( $args{'Base'} ) {
@@ -1310,7 +1192,7 @@ sub _AddLink {
my $TransString =
"Record $args{'Base'} $args{Type} record $args{'Target'}.";
- return ( $linkid, $self->loc( "Link created ([_1])", $TransString ) );
+ return ( 1, $self->loc( "Link created ([_1])", $TransString ) );
}
# }}}
@@ -1383,486 +1265,6 @@ sub _DeleteLink {
# }}}
-# }}}
-
-# {{{ Routines dealing with transactions
-
-# {{{ sub _NewTransaction
-
-=head2 _NewTransaction PARAMHASH
-
-Private function to create a new RT::Transaction object for this ticket update
-
-=cut
-
-sub _NewTransaction {
- my $self = shift;
- my %args = (
- TimeTaken => undef,
- Type => undef,
- OldValue => undef,
- NewValue => undef,
- OldReference => undef,
- NewReference => undef,
- ReferenceType => undef,
- Data => undef,
- Field => undef,
- MIMEObj => undef,
- ActivateScrips => 1,
- CommitScrips => 1,
- @_
- );
-
- my $old_ref = $args{'OldReference'};
- my $new_ref = $args{'NewReference'};
- my $ref_type = $args{'ReferenceType'};
- if ($old_ref or $new_ref) {
- $ref_type ||= ref($old_ref) || ref($new_ref);
- if (!$ref_type) {
- $RT::Logger->error("Reference type not specified for transaction");
- return;
- }
- $old_ref = $old_ref->Id if ref($old_ref);
- $new_ref = $new_ref->Id if ref($new_ref);
- }
-
- require RT::Transaction;
- my $trans = new RT::Transaction( $self->CurrentUser );
- my ( $transaction, $msg ) = $trans->Create(
- ObjectId => $self->Id,
- ObjectType => ref($self),
- TimeTaken => $args{'TimeTaken'},
- Type => $args{'Type'},
- Data => $args{'Data'},
- Field => $args{'Field'},
- NewValue => $args{'NewValue'},
- OldValue => $args{'OldValue'},
- NewReference => $new_ref,
- OldReference => $old_ref,
- ReferenceType => $ref_type,
- MIMEObj => $args{'MIMEObj'},
- ActivateScrips => $args{'ActivateScrips'},
- CommitScrips => $args{'CommitScrips'},
- );
-
- # Rationalize the object since we may have done things to it during the caching.
- $self->Load($self->Id);
-
- $RT::Logger->warning($msg) unless $transaction;
-
- $self->_SetLastUpdated;
-
- if ( defined $args{'TimeTaken'} ) {
- $self->_UpdateTimeTaken( $args{'TimeTaken'} );
- }
- if ( $RT::UseTransactionBatch and $transaction ) {
- push @{$self->{_TransactionBatch}}, $trans;
- }
- return ( $transaction, $msg, $trans );
-}
-
-# }}}
-
-# {{{ sub Transactions
-
-=head2 Transactions
-
- Returns an RT::Transactions object of all transactions on this record object
-
-=cut
-
-sub Transactions {
- my $self = shift;
-
- use RT::Transactions;
- my $transactions = RT::Transactions->new( $self->CurrentUser );
-
- #If the user has no rights, return an empty object
- $transactions->Limit(
- FIELD => 'ObjectId',
- VALUE => $self->id,
- );
- $transactions->Limit(
- FIELD => 'ObjectType',
- VALUE => ref($self),
- );
-
- return ($transactions);
-}
-
-# }}}
-# }}}
-#
-# {{{ Routines dealing with custom fields
-
-sub CustomFields {
- my $self = shift;
- my $cfs = RT::CustomFields->new( $self->CurrentUser );
-
- # XXX handle multiple types properly
- $cfs->LimitToLookupType( $self->CustomFieldLookupType );
- $cfs->LimitToGlobalOrObjectId(
- $self->_LookupId( $self->CustomFieldLookupType ) );
-
- return $cfs;
-}
-
-# TODO: This _only_ works for RT::Class classes. it doesn't work, for example, for RT::FM classes.
-
-sub _LookupId {
- my $self = shift;
- my $lookup = shift;
- my @classes = ($lookup =~ /RT::(\w+)-/g);
-
- my $object = $self;
- foreach my $class (reverse @classes) {
- my $method = "${class}Obj";
- $object = $object->$method;
- }
-
- return $object->Id;
-}
-
-
-=head2 CustomFieldLookupType
-
-Returns the path RT uses to figure out which custom fields apply to this object.
-
-=cut
-
-sub CustomFieldLookupType {
- my $self = shift;
- return ref($self);
-}
-
-#TODO Deprecated API. Destroy in 3.6
-sub _LookupTypes {
- my $self = shift;
- $RT::Logger->warning("_LookupTypes call is deprecated. Replace with CustomFieldLookupType");
- $RT::Logger->warning("Besides, it was a private API. Were you doing using it?");
-
- return($self->CustomFieldLookupType);
-
-}
-
-# {{{ AddCustomFieldValue
-
-=head2 AddCustomFieldValue { Field => FIELD, Value => VALUE }
-
-VALUE should be a string.
-FIELD can be a CustomField object OR a CustomField ID.
-
-
-Adds VALUE as a value of CustomField FIELD. If this is a single-value custom field,
-deletes the old value.
-If VALUE is not a valid value for the custom field, returns
-(0, 'Error message' ) otherwise, returns (1, 'Success Message')
-
-=cut
-
-sub AddCustomFieldValue {
- my $self = shift;
- $self->_AddCustomFieldValue(@_);
-}
-
-sub _AddCustomFieldValue {
- my $self = shift;
- my %args = (
- Field => undef,
- Value => undef,
- RecordTransaction => 1,
- @_
- );
-
- my $cf = $self->LoadCustomFieldByIdentifier($args{'Field'});
-
- unless ( $cf->Id ) {
- return ( 0, $self->loc( "Custom field [_1] not found", $args{'Field'} ) );
- }
-
- my $OCFs = $self->CustomFields;
- $OCFs->Limit( FIELD => 'id', VALUE => $cf->Id );
- unless ( $OCFs->Count ) {
- return (
- 0,
- $self->loc(
- "Custom field [_1] does not apply to this object",
- $args{'Field'}
- )
- );
- }
- # Load up a ObjectCustomFieldValues object for this custom field and this ticket
- my $values = $cf->ValuesForObject($self);
-
- unless ( $cf->ValidateValue( $args{'Value'} ) ) {
- return ( 0, $self->loc("Invalid value for custom field") );
- }
-
- # If the custom field only accepts a certain # of values, delete the existing
- # value and record a "changed from foo to bar" transaction
- unless ( $cf->UnlimitedValues) {
-
- # We need to whack any old values here. In most cases, the custom field should
- # only have one value to delete. In the pathalogical case, this custom field
- # used to be a multiple and we have many values to whack....
- my $cf_values = $values->Count;
-
- if ( $cf_values > $cf->MaxValues ) {
- my $i = 0; #We want to delete all but the max we can currently have , so we can then
- # execute the same code to "change" the value from old to new
- while ( my $value = $values->Next ) {
- $i++;
- if ( $i < $cf_values ) {
- my ( $val, $msg ) = $cf->DeleteValueForObject(
- Object => $self,
- Content => $value->Content
- );
- unless ($val) {
- return ( 0, $msg );
- }
- my ( $TransactionId, $Msg, $TransactionObj ) =
- $self->_NewTransaction(
- Type => 'CustomField',
- Field => $cf->Id,
- OldReference => $value,
- );
- }
- }
- }
-
- my ( $old_value, $old_content );
- if ( $old_value = $cf->ValuesForObject($self)->First ) {
- $old_content = $old_value->Content();
- return (1) if( $old_content eq $args{'Value'} && $old_value->LargeContent eq $args{'LargeContent'});;
- }
-
- my ( $new_value_id, $value_msg ) = $cf->AddValueForObject(
- Object => $self,
- Content => $args{'Value'},
- LargeContent => $args{'LargeContent'},
- ContentType => $args{'ContentType'},
- );
-
- unless ($new_value_id) {
- return ( 0, $self->loc( "Could not add new custom field value. [_1] ",, $value_msg));
- }
-
- my $new_value = RT::ObjectCustomFieldValue->new( $self->CurrentUser );
- $new_value->Load($new_value_id);
-
- # now that adding the new value was successful, delete the old one
- if ($old_value) {
- my ( $val, $msg ) = $old_value->Delete();
- unless ($val) {
- return ( 0, $msg );
- }
- }
-
- if ( $args{'RecordTransaction'} ) {
- my ( $TransactionId, $Msg, $TransactionObj ) =
- $self->_NewTransaction(
- Type => 'CustomField',
- Field => $cf->Id,
- OldReference => $old_value,
- NewReference => $new_value,
- );
- }
-
- if ( $old_value eq '' ) {
- return ( 1, $self->loc( "[_1] [_2] added", $cf->Name, $new_value->Content ));
- }
- elsif ( $new_value->Content eq '' ) {
- return ( 1,
- $self->loc( "[_1] [_2] deleted", $cf->Name, $old_value->Content ) );
- }
- else {
- return ( 1, $self->loc( "[_1] [_2] changed to [_3]", $cf->Name, $old_content, $new_value->Content));
- }
-
- }
-
- # otherwise, just add a new value and record "new value added"
- else {
- my ($new_value_id) = $cf->AddValueForObject(
- Object => $self,
- Content => $args{'Value'},
- LargeContent => $args{'LargeContent'},
- ContentType => $args{'ContentType'},
- );
-
- unless ($new_value_id) {
- return ( 0, $self->loc("Could not add new custom field value. ") );
- }
- if ( $args{'RecordTransaction'} ) {
- my ( $TransactionId, $Msg, $TransactionObj ) =
- $self->_NewTransaction(
- Type => 'CustomField',
- Field => $cf->Id,
- NewReference => $new_value_id,
- ReferenceType => 'RT::ObjectCustomFieldValue',
- );
- unless ($TransactionId) {
- return ( 0,
- $self->loc( "Couldn't create a transaction: [_1]", $Msg ) );
- }
- }
- return ( 1, $self->loc( "[_1] added as a value for [_2]", $args{'Value'}, $cf->Name));
- }
-
-}
-
-# }}}
-
-# {{{ DeleteCustomFieldValue
-
-=head2 DeleteCustomFieldValue { Field => FIELD, Value => VALUE }
-
-Deletes VALUE as a value of CustomField FIELD.
-
-VALUE can be a string, a CustomFieldValue or a ObjectCustomFieldValue.
-
-If VALUE is not a valid value for the custom field, returns
-(0, 'Error message' ) otherwise, returns (1, 'Success Message')
-
-=cut
-
-sub DeleteCustomFieldValue {
- my $self = shift;
- my %args = (
- Field => undef,
- Value => undef,
- ValueId => undef,
- @_
- );
-
- my $cf = $self->LoadCustomFieldByIdentifier($args{'Field'});
-
- unless ( $cf->Id ) {
- return ( 0, $self->loc( "Custom field [_1] not found", $args{'Field'} ) );
- }
- my ( $val, $msg ) = $cf->DeleteValueForObject(
- Object => $self,
- Id => $args{'ValueId'},
- Content => $args{'Value'},
- );
- unless ($val) {
- return ( 0, $msg );
- }
- my ( $TransactionId, $Msg, $TransactionObj ) = $self->_NewTransaction(
- Type => 'CustomField',
- Field => $cf->Id,
- OldReference => $val,
- ReferenceType => 'RT::ObjectCustomFieldValue',
- );
- unless ($TransactionId) {
- return ( 0, $self->loc( "Couldn't create a transaction: [_1]", $Msg ) );
- }
-
- return (
- $TransactionId,
- $self->loc(
- "[_1] is no longer a value for custom field [_2]",
- $TransactionObj->OldValue, $cf->Name
- )
- );
-}
-
-# }}}
-
-# {{{ FirstCustomFieldValue
-
-=head2 FirstCustomFieldValue FIELD
-
-Return the content of the first value of CustomField FIELD for this ticket
-Takes a field id or name
-
-=cut
-
-sub FirstCustomFieldValue {
- my $self = shift;
- my $field = shift;
- my $values = $self->CustomFieldValues($field);
- if ($values->First) {
- return $values->First->Content;
- } else {
- return undef;
- }
-
-}
-
-
-
-# {{{ CustomFieldValues
-
-=head2 CustomFieldValues FIELD
-
-Return a ObjectCustomFieldValues object of all values of the CustomField whose
-id or Name is FIELD for this record.
-
-Returns an RT::ObjectCustomFieldValues object
-
-=cut
-
-sub CustomFieldValues {
- my $self = shift;
- my $field = shift;
-
- if ($field) {
- my $cf = $self->LoadCustomFieldByIdentifier($field);
-
- # we were asked to search on a custom field we couldn't fine
- unless ( $cf->id ) {
- return RT::ObjectCustomFieldValues->new( $self->CurrentUser );
- }
- return ( $cf->ValuesForObject($self) );
- }
-
- # we're not limiting to a specific custom field;
- my $ocfs = RT::ObjectCustomFieldValues->new( $self->CurrentUser );
- $ocfs->LimitToObject($self);
- return $ocfs;
-
-}
-
-=head2 CustomField IDENTIFER
-
-Find the custom field has id or name IDENTIFIER for this object.
-
-If no valid field is found, returns an empty RT::CustomField object.
-
-=cut
-
-sub LoadCustomFieldByIdentifier {
- my $self = shift;
- my $field = shift;
-
- my $cf = RT::CustomField->new($self->CurrentUser);
-
- if ( UNIVERSAL::isa( $field, "RT::CustomField" ) ) {
- $cf->LoadById( $field->id );
- }
- elsif ($field =~ /^\d+$/) {
- $cf = RT::CustomField->new($self->CurrentUser);
- $cf->Load($field);
- } else {
-
- my $cfs = $self->CustomFields($self->CurrentUser);
- $cfs->Limit(FIELD => 'Name', VALUE => $field);
- $cf = $cfs->First || RT::CustomField->new($self->CurrentUser);
- }
- return $cf;
-}
-
-
-# }}}
-
-# }}}
-
-# }}}
-
-sub BasicColumns {
-}
-
eval "require RT::Record_Vendor";
die $@ if ($@ && $@ !~ qr{^Can't locate RT/Record_Vendor.pm});
eval "require RT::Record_Local";