summaryrefslogtreecommitdiff
path: root/rt/lib/RT/Transaction.pm
diff options
context:
space:
mode:
Diffstat (limited to 'rt/lib/RT/Transaction.pm')
-rwxr-xr-xrt/lib/RT/Transaction.pm895
1 files changed, 657 insertions, 238 deletions
diff --git a/rt/lib/RT/Transaction.pm b/rt/lib/RT/Transaction.pm
index ca491a6c7..ee1f069b2 100755
--- a/rt/lib/RT/Transaction.pm
+++ b/rt/lib/RT/Transaction.pm
@@ -1,364 +1,783 @@
-# BEGIN LICENSE BLOCK
-#
-# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
-#
-# (Except where explictly superceded by other copyright notices)
-#
-# This work is made available to you under the terms of Version 2 of
-# the GNU General Public License. A copy of that license should have
-# been provided with this software, but in any event can be snarfed
-# from www.gnu.org.
-#
-# This work is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# Unless otherwise specified, all modifications, corrections or
-# extensions to this work which alter its source code become the
-# property of Best Practical Solutions, LLC when submitted for
-# inclusion in the work.
-#
-#
-# END LICENSE BLOCK
-# Autogenerated by DBIx::SearchBuilder factory (by <jesse@bestpractical.com>)
-# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.
-#
-# !! DO NOT EDIT THIS FILE !!
-#
-
-use strict;
-
+# $Header: /home/cvs/cvsroot/freeside/rt/lib/RT/Transaction.pm,v 1.1 2002-08-12 06:17:07 ivan Exp $
+# Copyright 1999-2001 Jesse Vincent <jesse@fsck.com>
+# Released under the terms of the GNU Public License
=head1 NAME
-RT::Transaction
-
+ RT::Transaction - RT\'s transaction object
=head1 SYNOPSIS
-=head1 DESCRIPTION
-
-=head1 METHODS
-
-=cut
-
-package RT::Transaction;
-use RT::Record;
-use RT::Ticket;
-
-
-use vars qw( @ISA );
-@ISA= qw( RT::Record );
+ use RT::Transaction;
-sub _Init {
- my $self = shift;
- $self->Table('Transactions');
- $self->SUPER::_Init(@_);
-}
+=head1 DESCRIPTION
+Each RT::Transaction describes an atomic change to a ticket object
+or an update to an RT::Ticket object.
+It can have arbitrary MIME attachments.
+=head1 METHODS
-=item Create PARAMHASH
+=begin testing
-Create takes a hash of values and creates a row in the database:
+ok(require RT::TestHarness);
+ok(require RT::Transaction);
- int(11) 'EffectiveTicket'.
- int(11) 'Ticket'.
- int(11) 'TimeTaken'.
- varchar(20) 'Type'.
- varchar(40) 'Field'.
- varchar(255) 'OldValue'.
- varchar(255) 'NewValue'.
- varchar(100) 'Data'.
+=end testing
=cut
+package RT::Transaction;
+use RT::Record;
+@ISA= qw(RT::Record);
+
+use RT::Attachments;
-
-sub Create {
+# {{{ sub _Init
+sub _Init {
my $self = shift;
- my %args = (
- EffectiveTicket => '0',
- Ticket => '0',
- TimeTaken => '0',
- Type => '',
- Field => '',
- OldValue => '',
- NewValue => '',
- Data => '',
-
- @_);
- $self->SUPER::Create(
- EffectiveTicket => $args{'EffectiveTicket'},
- Ticket => $args{'Ticket'},
- TimeTaken => $args{'TimeTaken'},
- Type => $args{'Type'},
- Field => $args{'Field'},
- OldValue => $args{'OldValue'},
- NewValue => $args{'NewValue'},
- Data => $args{'Data'},
-);
+ $self->{'table'} = "Transactions";
+ return ($self->SUPER::_Init(@_));
}
+# }}}
+# {{{ sub Create
+=head2 Create
-=item id
+Create a new transaction.
-Returns the current value of id.
-(In the database, id is stored as int(11).)
+This routine should _never_ be called anything other Than RT::Ticket. It should not be called
+from client code. Ever. Not ever. If you do this, we will hunt you down. and break your kneecaps.
+Then the unpleasant stuff will start.
+TODO: Document what gets passed to this
=cut
+sub Create {
+ my $self = shift;
+ my %args = ( id => undef,
+ TimeTaken => 0,
+ Ticket => 0 ,
+ Type => 'undefined',
+ Data => '',
+ Field => undef,
+ OldValue => undef,
+ NewValue => undef,
+ MIMEObj => undef,
+ ActivateScrips => 1,
+ @_
+ );
+
+ #if we didn't specify a ticket, we need to bail
+ unless ( $args{'Ticket'} ) {
+ return(0, "RT::Transaction->Create couldn't, as you didn't specify a ticket id");
+ }
+
+ #lets create our transaction
+ my $id = $self->SUPER::Create(Ticket => $args{'Ticket'},
+ TimeTaken => $args{'TimeTaken'},
+ Type => $args{'Type'},
+ Data => $args{'Data'},
+ Field => $args{'Field'},
+ OldValue => $args{'OldValue'},
+ NewValue => $args{'NewValue'},
+ Created => $args{'Created'}
+ );
+ $self->Load($id);
+ $self->_Attach($args{'MIMEObj'})
+ if defined $args{'MIMEObj'};
+
+ #Provide a way to turn off scrips if we need to
+ if ($args{'ActivateScrips'}) {
+
+ #We're really going to need a non-acled ticket for the scrips to work
+ my $TicketAsSystem = RT::Ticket->new($RT::SystemUser);
+ $TicketAsSystem->Load($args{'Ticket'}) ||
+ $RT::Logger->err("$self couldn't load ticket $args{'Ticket'}\n");
+
+ my $TransAsSystem = RT::Transaction->new($RT::SystemUser);
+ $TransAsSystem->Load($self->id) ||
+ $RT::Logger->err("$self couldn't load a copy of itself as superuser\n");
+
+ # {{{ Deal with Scrips
+
+ #Load a scripscopes object
+ use RT::Scrips;
+ my $PossibleScrips = RT::Scrips->new($RT::SystemUser);
+
+ $PossibleScrips->LimitToQueue($TicketAsSystem->QueueObj->Id); #Limit it to $Ticket->QueueObj->Id
+ $PossibleScrips->LimitToGlobal(); # or to "global"
+ my $ConditionsAlias = $PossibleScrips->NewAlias('ScripConditions');
+
+ $PossibleScrips->Join(ALIAS1 => 'main', FIELD1 => 'ScripCondition',
+ ALIAS2 => $ConditionsAlias, FIELD2=> 'id');
+
+
+ #We only want things where the scrip applies to this sort of transaction
+ $PossibleScrips->Limit(ALIAS=> $ConditionsAlias,
+ FIELD=>'ApplicableTransTypes',
+ OPERATOR => 'LIKE',
+ VALUE => $args{'Type'},
+ ENTRYAGGREGATOR => 'OR',
+ );
+
+ # Or where the scrip applies to any transaction
+ $PossibleScrips->Limit(ALIAS=> $ConditionsAlias,
+ FIELD=>'ApplicableTransTypes',
+ OPERATOR => 'LIKE',
+ VALUE => "Any",
+ ENTRYAGGREGATOR => 'OR',
+ );
+
+ #Iterate through each script and check it's applicability.
+
+ while (my $Scrip = $PossibleScrips->Next()) {
+
+ #TODO: properly deal with errors raised in this scrip loop
+
+ #$RT::Logger->debug("$self now dealing with ".$Scrip->Id. "\n");
+ eval {
+ local $SIG{__DIE__} = sub { $RT::Logger->error($_[0])};
+
+
+ #Load the scrip's Condition object
+ $Scrip->ConditionObj->LoadCondition(TicketObj => $TicketAsSystem,
+ TransactionObj => $TransAsSystem);
+
+
+ #If it's applicable, prepare and commit it
+
+ $RT::Logger->debug ("$self: Checking condition ".$Scrip->ConditionObj->Name. "...\n");
+
+ if ( $Scrip->IsApplicable() ) {
+
+ $RT::Logger->debug ("$self: Matches condition ".$Scrip->ConditionObj->Name. "...\n");
+ #TODO: handle some errors here
+
+ $Scrip->ActionObj->LoadAction(TicketObj => $TicketAsSystem,
+ TransactionObj => $TransAsSystem);
+
+
+ if ($Scrip->Prepare()) {
+ $RT::Logger->debug("$self: Prepared " .
+ $Scrip->ActionObj->Name . "\n");
+ if ($Scrip->Commit()) {
+ $RT::Logger->debug("$self: Committed " .
+ $Scrip->ActionObj->Name . "\n");
+ }
+ else {
+ $RT::Logger->info("$self: Failed to commit ".
+ $Scrip->ActionObj->Name . "\n");
+ }
+ }
+ else {
+ $RT::Logger->info("$self: Failed to prepare " .
+ $Scrip->ActionObj->Name . "\n");
+ }
+
+ #We're done with it. lets clean up.
+ #TODO: something else isn't letting these get garbage collected. check em out.
+ $Scrip->ActionObj->DESTROY();
+ $Scrip->ConditionObj->DESTROY;
+ }
+
+
+ else {
+ $RT::Logger->debug ("$self: Doesn't match condition ".$Scrip->ConditionObj->Name. "...\n");
+
+ # TODO: why doesn't this catch all the ScripObjs we create.
+ # and why do we explictly need to destroy them?
+ $Scrip->ConditionObj->DESTROY;
+ }
+ }
+ }
+
+ # }}}
+
+ }
+
+ return ($id, "Transaction Created");
+}
-=item EffectiveTicket
+# }}}
-Returns the current value of EffectiveTicket.
-(In the database, EffectiveTicket is stored as int(11).)
+# {{{ sub Delete
+sub Delete {
+ my $self = shift;
+ return (0, 'Deleting this object could break referential integrity');
+}
+# }}}
-=item SetEffectiveTicket VALUE
+# {{{ Routines dealing with Attachments
+# {{{ sub Message
-Set EffectiveTicket to VALUE.
-Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, EffectiveTicket will be stored as a int(11).)
+=head2 Message
+ Returns the RT::Attachments Object which contains the "top-level" object
+ attachment for this transaction
=cut
+sub Message {
-=item Ticket
-
-Returns the current value of Ticket.
-(In the database, Ticket is stored as int(11).)
-
-
-
-=item SetTicket VALUE
-
-
-Set Ticket to VALUE.
-Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, Ticket will be stored as a int(11).)
+ my $self = shift;
+
+ if (!defined ($self->{'message'}) ){
+
+ $self->{'message'} = new RT::Attachments($self->CurrentUser);
+ $self->{'message'}->Limit(FIELD => 'TransactionId',
+ VALUE => $self->Id);
+
+ $self->{'message'}->ChildrenOf(0);
+ }
+ return($self->{'message'});
+}
+# }}}
+# {{{ sub Content
-=cut
+=head2 Content PARAMHASH
+If this transaction has attached mime objects, returns the first text/ part.
+Otherwise, returns undef.
-=item TicketObj
-
-Returns the Ticket Object which has the id returned by Ticket
+Takes a paramhash. If the $args{'Quote'} parameter is set, wraps this message
+at $args{'Wrap'}. $args{'Wrap'} defaults to 70.
=cut
-sub TicketObj {
- my $self = shift;
- my $Ticket = RT::Ticket->new($self->CurrentUser);
- $Ticket->Load($self->__Value('Ticket'));
- return($Ticket);
+sub Content {
+ my $self = shift;
+ my %args = ( Quote => 0,
+ Wrap => 70,
+ @_ );
+
+ my $content = undef;
+
+ # If we don\'t have any content, return undef now.
+ unless ($self->Message->First) {
+ return (undef);
+ }
+
+ # Get the set of toplevel attachments to this transaction.
+ my $MIMEObj = $self->Message->First();
+
+ # If it's a message or a plain part, just return the
+ # body.
+ if ($MIMEObj->ContentType() =~ '^(text|message)(/|$)') {
+ $content = $MIMEObj->Content();
+ }
+
+ # If it's a multipart object, first try returning the first
+ # text/plain part.
+
+ elsif ($MIMEObj->ContentType() =~ '^multipart/') {
+ my $plain_parts = $MIMEObj->Children();
+ $plain_parts->ContentType(VALUE => 'text/plain');
+
+ # If we actully found a part, return its content
+ if ($plain_parts->First &&
+ $plain_parts->First->Content ne '') {
+ $content = $plain_parts->First->Content;
+ }
+
+ # If that fails, return the first text/ or message/ part
+ # which has some content.
+
+ else {
+ my $all_parts = $MIMEObj->Children();
+ while (($content == undef) &&
+ (my $part = $all_parts->Next)) {
+ if (($part->ContentType() =~ '^(text|message)(/|$)') and
+ ($part->Content())) {
+ $content = $part->Content;
+ }
+ }
+ }
+
+ }
+ # If all else fails, return a message that we couldn't find
+ # any content
+ else {
+ $content = 'This transaction appears to have no content';
+ }
+
+ if ($args{'Quote'}) {
+ # Remove quoted signature.
+ $content =~ s/\n-- \n(.*)$//s;
+
+ # What's the longest line like?
+ foreach (split (/\n/,$content)) {
+ $max=length if ( length > $max);
+ }
+
+ if ($max>76) {
+ require Text::Wrapper;
+ my $wrapper=new Text::Wrapper
+ (
+ columns => $args{'Wrap'},
+ body_start => ($max > 70*3 ? ' ' : ''),
+ par_start => ''
+ );
+ $content=$wrapper->wrap($content);
+ }
+
+ $content =~ s/^/> /gm;
+ $content = '[' . $self->CreatorObj->Name() . ' - ' . $self->CreatedAsString()
+ . "]:\n\n"
+ . $content . "\n\n";
+
+ }
+
+ return ($content);
}
+# }}}
-=item TimeTaken
-
-Returns the current value of TimeTaken.
-(In the database, TimeTaken is stored as int(11).)
-
-
-
-=item SetTimeTaken VALUE
-
-
-Set TimeTaken to VALUE.
-Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, TimeTaken will be stored as a int(11).)
+# {{{ sub Subject
+=head2 Subject
+If this transaction has attached mime objects, returns the first one's subject
+Otherwise, returns null
+
=cut
+sub Subject {
+ my $self = shift;
+ if ($self->Message->First) {
+ return ($self->Message->First->Subject);
+ }
+ else {
+ return (undef);
+ }
+}
+# }}}
-=item Type
-
-Returns the current value of Type.
-(In the database, Type is stored as varchar(20).)
-
-
-
-=item SetType VALUE
-
+# {{{ sub Attachments
-Set Type to VALUE.
-Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, Type will be stored as a varchar(20).)
+=head2 Attachments
+ Returns all the RT::Attachment objects which are attached
+to this transaction. Takes an optional parameter, which is
+a ContentType that Attachments should be restricted to.
=cut
-=item Field
-
-Returns the current value of Field.
-(In the database, Field is stored as varchar(40).)
-
-
+sub Attachments {
+ my $self = shift;
+ my $Types = '';
+ $Types = shift if (@_);
+
+ my $Attachments = new RT::Attachments($self->CurrentUser);
+
+ #If it's a comment, return an empty object if they don't have the right to see it
+ if ($self->Type eq 'Comment') {
+ unless ($self->CurrentUserHasRight('ShowTicketComments')) {
+ return ($Attachments);
+ }
+ }
+ #if they ain't got rights to see, return an empty object
+ else {
+ unless ($self->CurrentUserHasRight('ShowTicket')) {
+ return ($Attachments);
+ }
+ }
+
+ $Attachments->Limit(FIELD => 'TransactionId',
+ VALUE => $self->Id);
+
+ # Get the attachments in the order they're put into
+ # the database. Arguably, we should be returning a tree
+ # of attachments, not a set...but no current app seems to need
+ # it.
+
+ $Attachments->OrderBy(ALIAS => 'main',
+ FIELD => 'Id',
+ ORDER => 'asc');
+
+ if ($Types) {
+ $Attachments->ContentType( VALUE => "$Types",
+ OPERATOR => "LIKE");
+ }
+
+
+ return($Attachments);
+
+}
-=item SetField VALUE
+# }}}
+# {{{ sub _Attach
-Set Field to VALUE.
-Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, Field will be stored as a varchar(40).)
+=head2 _Attach
+A private method used to attach a mime object to this transaction.
=cut
+sub _Attach {
+ my $self = shift;
+ my $MIMEObject = shift;
+
+ if (!defined($MIMEObject)) {
+ $RT::Logger->error("$self _Attach: We can't attach a mime object if you don't give us one.\n");
+ return(0, "$self: no attachment specified");
+ }
+
+
+ use RT::Attachment;
+ my $Attachment = new RT::Attachment ($self->CurrentUser);
+ $Attachment->Create(TransactionId => $self->Id,
+ Attachment => $MIMEObject);
+ return ($Attachment, "Attachment created");
+
+}
-=item OldValue
-
-Returns the current value of OldValue.
-(In the database, OldValue is stored as varchar(255).)
-
+# }}}
+# }}}
-=item SetOldValue VALUE
+# {{{ Routines dealing with Transaction Attributes
+# {{{ sub TicketObj
-Set OldValue to VALUE.
-Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, OldValue will be stored as a varchar(255).)
+=head2 TicketObj
+Returns this transaction's ticket object.
=cut
+sub TicketObj {
+ my $self = shift;
+ if (! exists $self->{'TicketObj'}) {
+ $self->{'TicketObj'} = new RT::Ticket($self->CurrentUser);
+ $self->{'TicketObj'}->Load($self->Ticket);
+ }
+
+ return $self->{'TicketObj'};
+}
+# }}}
-=item NewValue
-
-Returns the current value of NewValue.
-(In the database, NewValue is stored as varchar(255).)
-
-
-
-=item SetNewValue VALUE
-
+# {{{ sub Description
-Set NewValue to VALUE.
-Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, NewValue will be stored as a varchar(255).)
+=head2 Description
+Returns a text string which describes this transaction
=cut
-=item Data
-
-Returns the current value of Data.
-(In the database, Data is stored as varchar(100).)
-
+sub Description {
+ my $self = shift;
+ #Check those ACLs
+ #If it's a comment, we need to be extra special careful
+ if ($self->__Value('Type') eq 'Comment') {
+ unless ($self->CurrentUserHasRight('ShowTicketComments')) {
+ return (0, "Permission Denied");
+ }
+ }
+
+ #if they ain't got rights to see, don't let em
+ else {
+ unless ($self->CurrentUserHasRight('ShowTicket')) {
+ return (0, "Permission Denied");
+ }
+ }
+
+ if (!defined($self->Type)) {
+ return("No transaction type specified");
+ }
+
+ return ($self->BriefDescription . " by " . $self->CreatorObj->Name);
+}
-=item SetData VALUE
+# }}}
+# {{{ sub BriefDescription
-Set Data to VALUE.
-Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
-(In the database, Data will be stored as a varchar(100).)
+=head2 BriefDescription
+Returns a text string which briefly describes this transaction
=cut
-=item Creator
+sub BriefDescription {
+ my $self = shift;
-Returns the current value of Creator.
-(In the database, Creator is stored as int(11).)
+ #Check those ACLs
+ #If it's a comment, we need to be extra special careful
+ if ($self->__Value('Type') eq 'Comment') {
+ unless ($self->CurrentUserHasRight('ShowTicketComments')) {
+ return (0, "Permission Denied");
+ }
+ }
+
+ #if they ain't got rights to see, don't let em
+ else {
+ unless ($self->CurrentUserHasRight('ShowTicket')) {
+ return (0, "Permission Denied");
+ }
+ }
+
+ if (!defined($self->Type)) {
+ return("No transaction type specified");
+ }
+
+ if ($self->Type eq 'Create'){
+ return("Ticket created");
+ }
+ elsif ($self->Type =~ /Status/) {
+ if ($self->Field eq 'Status') {
+ if ($self->NewValue eq 'dead') {
+ return ("Ticket killed");
+ }
+ else {
+ return( "Status changed from ". $self->OldValue .
+ " to ". $self->NewValue);
+
+ }
+ }
+ # Generic:
+ return ($self->Field." changed from ".($self->OldValue||"(empty value)").
+ " to ".$self->NewValue );
+ }
+
+ if ($self->Type eq 'Correspond') {
+ return("Correspondence added");
+ }
+
+ elsif ($self->Type eq 'Comment') {
+ return( "Comments added");
+ }
+
+ elsif ($self->Type eq 'Keyword') {
+
+ my $field = 'Keyword';
+
+ if ($self->Field) {
+ my $keywordsel = new RT::KeywordSelect ($self->CurrentUser);
+ $keywordsel->Load($self->Field);
+ $field = $keywordsel->Name();
+ }
+
+ if ($self->OldValue eq '') {
+ return ($field." ".$self->NewValue." added");
+ }
+ elsif ($self->NewValue eq '') {
+ return ($field." ".$self->OldValue." deleted");
+
+ }
+ else {
+ return ($field." ".$self->OldValue . " changed to ".
+ $self->NewValue);
+ }
+ }
+
+ elsif ($self->Type eq 'Untake'){
+ return( "Untaken");
+ }
+
+ elsif ($self->Type eq "Take") {
+ return( "Taken");
+ }
+
+ elsif ($self->Type eq "Force") {
+ my $Old = RT::User->new($self->CurrentUser);
+ $Old->Load($self->OldValue);
+ my $New = RT::User->new($self->CurrentUser);
+ $New->Load($self->NewValue);
+ return "Owner forcibly changed from ".$Old->Name . " to ". $New->Name;
+ }
+ elsif ($self->Type eq "Steal") {
+ my $Old = RT::User->new($self->CurrentUser);
+ $Old->Load($self->OldValue);
+ return "Stolen from ".$Old->Name;
+ }
+
+ elsif ($self->Type eq "Give") {
+ my $New = RT::User->new($self->CurrentUser);
+ $New->Load($self->NewValue);
+ return( "Given to ".$New->Name);
+ }
+
+ elsif ($self->Type eq 'AddWatcher'){
+ return( $self->Field." ". $self->NewValue ." added");
+ }
+
+ elsif ($self->Type eq 'DelWatcher'){
+ return( $self->Field." ".$self->OldValue ." deleted");
+ }
+
+ elsif ($self->Type eq 'Subject') {
+ return( "Subject changed to ".$self->Data);
+ }
+ elsif ($self->Type eq 'Told') {
+ return( "User notified");
+ }
+
+ elsif ($self->Type eq 'AddLink') {
+ return ($self->Data);
+ }
+ elsif ($self->Type eq 'DeleteLink') {
+ return ($self->Data);
+ }
+ elsif ($self->Type eq 'Set') {
+ if ($self->Field eq 'Queue') {
+ my $q1 = new RT::Queue($self->CurrentUser);
+ $q1->Load($self->OldValue);
+ my $q2 = new RT::Queue($self->CurrentUser);
+ $q2->Load($self->NewValue);
+ return ($self->Field . " changed from " . $q1->Name . " to ".
+ $q2->Name);
+ }
+
+ # Write the date/time change at local time:
+ elsif ($self->Field =~ /Due|Starts|Started|Told/) {
+ my $t1 = new RT::Date($self->CurrentUser);
+ $t1->Set(Format => 'ISO', Value => $self->NewValue);
+ my $t2 = new RT::Date($self->CurrentUser);
+ $t2->Set(Format => 'ISO', Value => $self->OldValue);
+ return ($self->Field . " changed from " . $t2->AsString .
+ " to ".$t1->AsString);
+ }
+ else {
+ return ($self->Field . " changed from " . $self->OldValue .
+ " to ".$self->NewValue);
+ }
+ }
+ elsif ($self->Type eq 'PurgeTransaction') {
+ return ("Transaction ".$self->Data. " purged");
+ }
+ else {
+ return ("Default: ". $self->Type ."/". $self->Field .
+ " changed from " . $self->OldValue .
+ " to ".$self->NewValue);
+
+ }
+}
+# }}}
-=cut
+# {{{ Utility methods
+# {{{ sub IsInbound
-=item Created
-
-Returns the current value of Created.
-(In the database, Created is stored as datetime.)
+=head2 IsInbound
+Returns true if the creator of the transaction is a requestor of the ticket.
+Returns false otherwise
=cut
+sub IsInbound {
+ my $self=shift;
+ return ($self->TicketObj->IsRequestor($self->CreatorObj));
+}
+# }}}
+
+# }}}
+
+# {{{ sub _Accessible
+
+sub _Accessible {
+ my $self = shift;
+ my %Cols = (
+ TimeTaken => 'read',
+ Ticket => 'read/public',
+ Type=> 'read',
+ Field => 'read',
+ Data => 'read',
+ NewValue => 'read',
+ OldValue => 'read',
+ Creator => 'read/auto',
+ Created => 'read/auto',
+ );
+ return $self->SUPER::_Accessible(@_, %Cols);
+}
-sub _ClassAccessible {
- {
-
- id =>
- {read => 1, type => 'int(11)', default => ''},
- EffectiveTicket =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
- Ticket =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
- TimeTaken =>
- {read => 1, write => 1, type => 'int(11)', default => '0'},
- Type =>
- {read => 1, write => 1, type => 'varchar(20)', default => ''},
- Field =>
- {read => 1, write => 1, type => 'varchar(40)', default => ''},
- OldValue =>
- {read => 1, write => 1, type => 'varchar(255)', default => ''},
- NewValue =>
- {read => 1, write => 1, type => 'varchar(255)', default => ''},
- Data =>
- {read => 1, write => 1, type => 'varchar(100)', default => ''},
- Creator =>
- {read => 1, auto => 1, type => 'int(11)', default => '0'},
- Created =>
- {read => 1, auto => 1, type => 'datetime', default => ''},
-
- }
-};
+# }}}
+# }}}
- eval "require RT::Transaction_Overlay";
- if ($@ && $@ !~ qr{^Can't locate RT/Transaction_Overlay.pm}) {
- die $@;
- };
+# {{{ sub _Set
- eval "require RT::Transaction_Vendor";
- if ($@ && $@ !~ qr{^Can't locate RT/Transaction_Vendor.pm}) {
- die $@;
- };
+sub _Set {
+ my $self = shift;
+ return(0, 'Transactions are immutable');
+}
- eval "require RT::Transaction_Local";
- if ($@ && $@ !~ qr{^Can't locate RT/Transaction_Local.pm}) {
- die $@;
- };
+# }}}
+# {{{ sub _Value
+=head2 _Value
+Takes the name of a table column.
+Returns its value as a string, if the user passes an ACL check
-=head1 SEE ALSO
+=cut
-This class allows "overlay" methods to be placed
-into the following files _Overlay is for a System overlay by the original author,
-_Vendor is for 3rd-party vendor add-ons, while _Local is for site-local customizations.
+sub _Value {
-These overlay files can contain new subs or subs to replace existing subs in this module.
+ my $self = shift;
+ my $field = shift;
+
+
+ #if the field is public, return it.
+ if ($self->_Accessible($field, 'public')) {
+ return($self->__Value($field));
+
+ }
+ #If it's a comment, we need to be extra special careful
+ if ($self->__Value('Type') eq 'Comment') {
+ unless ($self->CurrentUserHasRight('ShowTicketComments')) {
+ return (undef);
+ }
+ }
+ #if they ain't got rights to see, don't let em
+ else {
+ unless ($self->CurrentUserHasRight('ShowTicket')) {
+ return (undef);
+ }
+ }
+
+ return($self->__Value($field));
+
+}
-If you'll be working with perl 5.6.0 or greater, each of these files should begin with the line
+# }}}
- no warnings qw(redefine);
+# {{{ sub CurrentUserHasRight
-so that perl does not kick and scream when you redefine a subroutine or variable in your overlay.
+=head2 CurrentUserHasRight RIGHT
-RT::Transaction_Overlay, RT::Transaction_Vendor, RT::Transaction_Local
+Calls $self->CurrentUser->HasQueueRight for the right passed in here.
+passed in here.
=cut
+sub CurrentUserHasRight {
+ my $self = shift;
+ my $right = shift;
+ return ($self->CurrentUser->HasQueueRight(Right => "$right",
+ TicketObj => $self->TicketObj));
+}
+
+# }}}
1;