diff options
Diffstat (limited to 'rt/lib/RT/Transaction.pm')
-rwxr-xr-x | rt/lib/RT/Transaction.pm | 895 |
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; |