#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/copyleft/gpl.html.
#
#
# CONTRIBUTION SUBMISSION POLICY:
# those contributions and any derivatives thereof.
#
# END BPS TAGGED BLOCK }}}
-
=head1 NAME
RT::Record - Base class for RT record objects
=cut
package RT::Record;
+
+use strict;
+use warnings;
+
+our @ISA;
+use base qw(RT::Base);
+
use RT::Date;
use RT::User;
use RT::Attributes;
-use RT::Base;
use DBIx::SearchBuilder::Record::Cachable;
+use Encode qw();
-use strict;
-use vars qw/@ISA $_TABLE_ATTR/;
+our $_TABLE_ATTR = { };
-@ISA = qw(RT::Base);
-if ($RT::DontCacheSearchBuilderRecords ) {
+if ( $RT::DontCacheSearchBuilderRecords ) {
push (@ISA, 'DBIx::SearchBuilder::Record');
} else {
push (@ISA, 'DBIx::SearchBuilder::Record::Cachable');
Description => $args{'Description'},
Content => $args{'Content'} );
-
+
# XXX TODO: Why won't RedoSearch work here?
$self->Attributes->_DoSearch;
=head2 FirstAttribute NAME
-Returns the value of the first attribute with the matching name
-for this object, or C<undef> if no such attributes exist.
+Returns the first attribute with the matching name for this object (as an
+L<RT::Attribute> object), or C<undef> if no such attributes exist.
+
+Note that if there is more than one attribute with the matching name on the
+object, the choice of which one to return is basically arbitrary. This may be
+made well-defined in the future.
=cut
}
-require Encode::compat if $] < 5.007001;
-require Encode;
-
-
-
sub __Value {
my $self = shift;
elsif ($RT::DropLongAttachments) {
# drop the attachment on the floor
- $RT::Logger->info( "$self: Dropped an attachment of size " . length($Body) . "\n" . "It started: " . substr( $Body, 0, 60 ) . "\n" );
+ $RT::Logger->info( "$self: Dropped an attachment of size "
+ . length($Body) . "\n"
+ . "It started: " . substr( $Body, 0, 60 ) . "\n"
+ );
return ("none", "Large attachment dropped" );
}
}
elsif ( $ContentEncoding && $ContentEncoding ne 'none' ) {
return ( $self->loc( "Unknown ContentEncoding [_1]", $ContentEncoding ) );
}
- if ( $ContentType eq 'text/plain' ) {
+ if ( RT::I18N::IsTextualContentType($ContentType) ) {
$Content = Encode::decode_utf8($Content) unless Encode::is_utf8($Content);
}
return ($Content);
);
+=head2 Update ARGSHASH
+
+Updates fields on an object for you using the proper Set methods,
+skipping unchanged values.
+
+ ARGSRef => a hashref of attributes => value for the update
+ AttributesRef => an arrayref of keys in ARGSRef that should be updated
+ AttributePrefix => a prefix that should be added to the attributes in AttributesRef
+ when looking up values in ARGSRef
+ Bare attributes are tried before prefixed attributes
+
+Returns a list of localized results of the update
+
+=cut
+
sub Update {
my $self = shift;
next if ( $value eq $self->$attribute() );
my $method = "Set$attribute";
my ( $code, $msg ) = $self->$method($value);
- my ($prefix) = ref($self) =~ /RT::(\w+)/;
+ my ($prefix) = ref($self) =~ /RT(?:.*)::(\w+)/;
# Default to $id, but use name if we can get it.
my $label = $self->id;
=head2 ReferredToBy
- This returns an RT::Links object which shows all references for which this ticket is a target
+This returns an L<RT::Links> object which shows all references for which this ticket is a target
=cut
# {{{ sub _Links
-=head2 Links DIRECTION TYPE
+=head2 Links DIRECTION [TYPE]
-return links to/from this object.
+Return links (L<RT::Links>) to/from this object.
+
+DIRECTION is either 'Base' or 'Target'.
+
+TYPE is a type of links to return, it can be omitted to get
+links of any type.
=cut
=head2 _AddLink
-Takes a paramhash of Type and one of Base or Target. Adds that link to this ticket.
+Takes a paramhash of Type and one of Base or Target. Adds that link to this object.
+
+Returns C<link id>, C<message> and C<exist> flag.
=cut
}
elsif ( $args{'Base'} ) {
$args{'Target'} = $self->URI();
- my $class = ref($self);
$remote_link = $args{'Base'};
$direction = 'Target';
}
elsif ( $args{'Target'} ) {
$args{'Base'} = $self->URI();
- my $class = ref($self);
$remote_link = $args{'Target'};
$direction = 'Base';
}
Target => $args{'Target'} );
if ( $old_link->Id ) {
$RT::Logger->debug("$self Somebody tried to duplicate a link");
- return ( $old_link->id, $self->loc("Link already exists") );
+ return ( $old_link->id, $self->loc("Link already exists"), 1 );
}
# }}}
$direction='Base';
}
else {
- $RT::Logger->debug("$self: Base or Target must be specified\n");
+ $RT::Logger->error("Base or Target must be specified\n");
return ( 0, $self->loc('Either base or target must be specified') );
}
$self->_SetLastUpdated;
- if ( defined $args{'TimeTaken'} ) {
+ if ( defined $args{'TimeTaken'} and $self->can('_UpdateTimeTaken')) {
$self->_UpdateTimeTaken( $args{'TimeTaken'} );
}
if ( $RT::UseTransactionBatch and $transaction ) {
- push @{$self->{_TransactionBatch}}, $trans;
+ push @{$self->{_TransactionBatch}}, $trans if $args{'CommitScrips'};
}
return ( $transaction, $msg, $trans );
}
);
}
}
+ $values->RedoSearch if $i; # redo search if have deleted at least one value
}
my ( $old_value, $old_content );
- if ( $old_value = $cf->ValuesForObject($self)->First ) {
+ if ( $old_value = $values->First ) {
$old_content = $old_value->Content();
return (1) if( $old_content eq $args{'Value'} && $old_value->LargeContent eq $args{'LargeContent'});;
}
);
unless ($new_value_id) {
- return ( 0, $self->loc( "Could not add new custom field value. [_1] ",, $value_msg));
+ return ( 0, $self->loc( "Could not add new custom field value: [_1]", $value_msg) );
}
my $new_value = RT::ObjectCustomFieldValue->new( $self->CurrentUser );
# otherwise, just add a new value and record "new value added"
else {
- my ($new_value_id) = $cf->AddValueForObject(
+ my ($new_value_id, $value_msg) = $cf->AddValueForObject(
Object => $self,
Content => $args{'Value'},
LargeContent => $args{'LargeContent'},
);
unless ($new_value_id) {
- return ( 0, $self->loc("Could not add new custom field value. ") );
+ return ( 0, $self->loc( "Could not add new custom field value: [_1]", $value_msg) );
}
if ( $args{'RecordTransaction'} ) {
my ( $TransactionId, $Msg, $TransactionObj ) =
} else {
my $cfs = $self->CustomFields($self->CurrentUser);
- $cfs->Limit(FIELD => 'Name', VALUE => $field);
+ $cfs->Limit(FIELD => 'Name', VALUE => $field, CASESENSITIVE => 0);
$cf = $cfs->First || RT::CustomField->new($self->CurrentUser);
}
return $cf;
sub BasicColumns {
}
+sub WikiBase {
+ return $RT::WebPath. "/index.html?q=";
+}
+
eval "require RT::Record_Vendor";
die $@ if ($@ && $@ !~ qr{^Can't locate RT/Record_Vendor.pm});
eval "require RT::Record_Local";