diff options
Diffstat (limited to 'rt/lib/RT/Scrip.pm')
-rwxr-xr-x | rt/lib/RT/Scrip.pm | 543 |
1 files changed, 341 insertions, 202 deletions
diff --git a/rt/lib/RT/Scrip.pm b/rt/lib/RT/Scrip.pm index b03d6b5..eedd406 100755 --- a/rt/lib/RT/Scrip.pm +++ b/rt/lib/RT/Scrip.pm @@ -67,13 +67,14 @@ package RT::Scrip; use strict; use warnings; - +use base 'RT::Record'; use RT::Queue; use RT::Template; use RT::ScripCondition; use RT::ScripAction; -use base 'RT::Record'; +use RT::Scrips; +use RT::ObjectScrip; sub Table {'Scrips'} @@ -104,7 +105,7 @@ sub Create { my $self = shift; my %args = ( Queue => 0, - Template => 0, # name or id + Template => undef, # name or id ScripAction => 0, # name or id ScripCondition => 0, # name or id Stage => 'TransactionCreate', @@ -147,7 +148,6 @@ sub Create { #TODO +++ validate input - require RT::ScripAction; return ( 0, $self->loc("Action is mandatory argument") ) unless $args{'ScripAction'}; my $action = RT::ScripAction->new( $self->CurrentUser ); @@ -155,15 +155,26 @@ sub Create { return ( 0, $self->loc( "Action '[_1]' not found", $args{'ScripAction'} ) ) unless $action->Id; - require RT::Template; return ( 0, $self->loc("Template is mandatory argument") ) unless $args{'Template'}; my $template = RT::Template->new( $self->CurrentUser ); - $template->Load( $args{'Template'} ); - return ( 0, $self->loc( "Template '[_1]' not found", $args{'Template'} ) ) - unless $template->Id; + if ( $args{'Template'} =~ /\D/ ) { + $template->LoadByName( Name => $args{'Template'}, Queue => $args{'Queue'} ); + return ( 0, $self->loc( "Global template '[_1]' not found", $args{'Template'} ) ) + if !$template->Id && !$args{'Queue'}; + return ( 0, $self->loc( "Global or queue specific template '[_1]' not found", $args{'Template'} ) ) + if !$template->Id; + } else { + $template->Load( $args{'Template'} ); + return ( 0, $self->loc( "Template '[_1]' not found", $args{'Template'} ) ) + unless $template->Id; + + return (0, $self->loc( "Template '[_1]' is not global" )) + if !$args{'Queue'} && $template->Queue; + return (0, $self->loc( "Template '[_1]' is not global nor queue specific" )) + if $args{'Queue'} && $template->Queue && $template->Queue != $args{'Queue'}; + } - require RT::ScripCondition; return ( 0, $self->loc("Condition is mandatory argument") ) unless $args{'ScripCondition'}; my $condition = RT::ScripCondition->new( $self->CurrentUser ); @@ -171,12 +182,18 @@ sub Create { return ( 0, $self->loc( "Condition '[_1]' not found", $args{'ScripCondition'} ) ) unless $condition->Id; + if ( $args{'Stage'} eq 'Disabled' ) { + $RT::Logger->warning("Disabled Stage is deprecated"); + $args{'Stage'} = 'TransactionCreate'; + $args{'Disabled'} = 1; + } + $args{'Disabled'} ||= 0; + my ( $id, $msg ) = $self->SUPER::Create( - Queue => $args{'Queue'}, - Template => $template->Id, + Template => $template->Name, ScripCondition => $condition->id, - Stage => $args{'Stage'}, ScripAction => $action->Id, + Disabled => $args{'Disabled'}, Description => $args{'Description'}, CustomPrepareCode => $args{'CustomPrepareCode'}, CustomCommitCode => $args{'CustomCommitCode'}, @@ -184,12 +201,16 @@ sub Create { ConditionRules => $args{'ConditionRules'}, ActionRules => $args{'ActionRules'}, ); - if ( $id ) { - return ( $id, $self->loc('Scrip Created') ); - } - else { - return ( $id, $msg ); - } + return ( $id, $msg ) unless $id; + + (my $status, $msg) = RT::ObjectScrip->new( $self->CurrentUser )->Add( + Scrip => $self, + Stage => $args{'Stage'}, + ObjectId => $args{'Queue'}, + ); + $RT::Logger->error( "Couldn't add scrip: $msg" ) unless $status; + + return ( $id, $self->loc('Scrip Created') ); } @@ -207,29 +228,154 @@ sub Delete { return ( 0, $self->loc('Permission Denied') ); } + RT::ObjectScrip->new( $self->CurrentUser )->DeleteAll( Scrip => $self ); + return ( $self->SUPER::Delete(@_) ); } +sub IsGlobal { return shift->IsAdded(0) } + +sub IsAdded { + my $self = shift; + my $record = RT::ObjectScrip->new( $self->CurrentUser ); + $record->LoadByCols( Scrip => $self->id, ObjectId => shift || 0 ); + return undef unless $record->id; + return $record; +} + +sub IsAddedToAny { + my $self = shift; + my $record = RT::ObjectScrip->new( $self->CurrentUser ); + $record->LoadByCols( Scrip => $self->id ); + return $record->id ? 1 : 0; +} + +sub AddedTo { + my $self = shift; + return RT::ObjectScrip->new( $self->CurrentUser ) + ->AddedTo( Scrip => $self ); +} + +sub NotAddedTo { + my $self = shift; + return RT::ObjectScrip->new( $self->CurrentUser ) + ->NotAddedTo( Scrip => $self ); +} + +=head2 AddToObject + +Adds (applies) the current scrip to the provided queue (ObjectId). +Accepts a param hash of: -=head2 QueueObj +=over -Retuns an RT::Queue object with this Scrip's queue +=item C<ObjectId> + +Queue name or id. 0 makes the scrip global. + +=item C<Stage> + +Stage to run in. Valid stages are TransactionCreate or +TransactionBatch. Defaults to TransactionCreate. As of RT 4.2, Disabled +is no longer a stage. + +=item C<Template> + +Name of global or queue-specific template for the scrip. Use 'Blank' for +non-notification scrips. + +=item C<SortOrder> + +Number indicating the relative order the scrip should run in. + +=back + +Returns (val, message). If val is false, the message contains an error +message. =cut -sub QueueObj { +sub AddToObject { my $self = shift; + my %args = @_%2? (ObjectId => @_) : (@_); + + # Default Stage explicitly rather than in %args assignment to handle + # Stage coming in set to undef. + $args{'Stage'} //= 'TransactionCreate'; - if ( !$self->{'QueueObj'} ) { - require RT::Queue; - $self->{'QueueObj'} = RT::Queue->new( $self->CurrentUser ); - $self->{'QueueObj'}->Load( $self->__Value('Queue') ); + my $queue; + if ( $args{'ObjectId'} ) { + $queue = RT::Queue->new( $self->CurrentUser ); + $queue->Load( $args{'ObjectId'} ); + return (0, $self->loc('Invalid queue')) + unless $queue->id; + + $args{'ObjectId'} = $queue->id; + } + return ( 0, $self->loc('Permission Denied') ) + unless $self->CurrentUser->PrincipalObj->HasRight( + Object => $queue || $RT::System, Right => 'ModifyScrips', + ) + ; + + my $tname = $self->Template; + my $template = RT::Template->new( $self->CurrentUser ); + $template->LoadByName( Queue => $queue? $queue->id : 0, Name => $tname ); + unless ( $template->id ) { + if ( $queue ) { + return (0, $self->loc('No template [_1] in queue [_2] or global', + $tname, $queue->Name||$queue->id)); + } else { + return (0, $self->loc('No global template [_1]', $tname)); + } } - return ( $self->{'QueueObj'} ); + + my $rec = RT::ObjectScrip->new( $self->CurrentUser ); + return $rec->Add( %args, Scrip => $self ); } +=head2 RemoveFromObject + +Removes the current scrip to the provided queue (ObjectId). + +Accepts a param hash of: + +=over + +=item C<ObjectId> +Queue name or id. 0 makes the scrip global. + +=back + +Returns (val, message). If val is false, the message contains an error +message. + +=cut + +sub RemoveFromObject { + my $self = shift; + my %args = @_%2? (ObjectId => @_) : (@_); + + my $queue; + if ( $args{'ObjectId'} ) { + $queue = RT::Queue->new( $self->CurrentUser ); + $queue->Load( $args{'ObjectId'} ); + return (0, $self->loc('Invalid queue id')) + unless $queue->id; + } + return ( 0, $self->loc('Permission Denied') ) + unless $self->CurrentUser->PrincipalObj->HasRight( + Object => $queue || $RT::System, Right => 'ModifyScrips', + ) + ; + + my $rec = RT::ObjectScrip->new( $self->CurrentUser ); + $rec->LoadByCols( Scrip => $self->id, ObjectId => $args{'ObjectId'} ); + return (0, $self->loc('Scrip is not added') ) unless $rec->id; + return $rec->Delete; +} =head2 ActionObj @@ -242,12 +388,8 @@ sub ActionObj { unless ( defined $self->{'ScripActionObj'} ) { require RT::ScripAction; - $self->{'ScripActionObj'} = RT::ScripAction->new( $self->CurrentUser ); - - #TODO: why are we loading Actions with templates like this. - # two separate methods might make more sense - $self->{'ScripActionObj'}->Load( $self->ScripAction, $self->Template ); + $self->{'ScripActionObj'}->Load( $self->ScripAction ); } return ( $self->{'ScripActionObj'} ); } @@ -291,17 +433,54 @@ Retuns an RT::Template object with this Scrip's Template sub TemplateObj { my $self = shift; + my $queue = shift; - unless ( defined $self->{'TemplateObj'} ) { - require RT::Template; - $self->{'TemplateObj'} = RT::Template->new( $self->CurrentUser ); - $self->{'TemplateObj'}->Load( $self->Template ); - } - return ( $self->{'TemplateObj'} ); + my $res = RT::Template->new( $self->CurrentUser ); + $res->LoadByName( Queue => $queue, Name => $self->Template ); + return $res; } +=head2 Stage + +Takes TicketObj named argument and returns scrip's stage when +added to ticket's queue. + +=cut + +sub Stage { + my $self = shift; + my %args = ( TicketObj => undef, @_ ); + my $queue = $args{'TicketObj'}->Queue; + my $rec = RT::ObjectScrip->new( $self->CurrentUser ); + $rec->LoadByCols( Scrip => $self->id, ObjectId => $queue ); + return $rec->Stage if $rec->id; + $rec->LoadByCols( Scrip => $self->id, ObjectId => 0 ); + return $rec->Stage if $rec->id; + + return undef; +} + +=head2 FriendlyStage($Stage) + +Helper function that returns a localized human-readable version of the +C<$Stage> argument. + +=cut + +sub FriendlyStage { + my ( $class, $stage ) = @_; + my $stage_i18n_lookup = { + TransactionCreate => 'Normal', # loc + TransactionBatch => 'Batch', # loc + TransactionBatchDisabled => 'Batch (disabled by config)', # loc + }; + $stage = 'TransactionBatchDisabled' + if $stage eq 'TransactionBatch' + and not RT->Config->Get('UseTransactionBatch'); + return $stage_i18n_lookup->{$stage}; +} =head2 Apply { TicketObj => undef, TransactionObj => undef} @@ -385,38 +564,46 @@ sub IsApplicable { my $return; eval { - my @Transactions; + my @Transactions; - if ( $self->Stage eq 'TransactionCreate') { - # Only look at our current Transaction - @Transactions = ( $args{'TransactionObj'} ); + my $stage = $self->Stage( TicketObj => $args{'TicketObj'} ); + unless ( $stage ) { + $RT::Logger->error( + "Scrip #". $self->id ." is not applied to" + ." queue #". $args{'TicketObj'}->Queue + ); + return (undef); } - elsif ( $self->Stage eq 'TransactionBatch') { - # Look at all Transactions in this Batch + elsif ( $stage eq 'TransactionCreate') { + # Only look at our current Transaction + @Transactions = ( $args{'TransactionObj'} ); + } + elsif ( $stage eq 'TransactionBatch') { + # Look at all Transactions in this Batch @Transactions = @{ $args{'TicketObj'}->TransactionBatch || [] }; } - else { - $RT::Logger->error( "Unknown Scrip stage:" . $self->Stage ); - return (undef); - } - my $ConditionObj = $self->ConditionObj; - foreach my $TransactionObj ( @Transactions ) { - # in TxnBatch stage we can select scrips that are not applicable to all txns - my $txn_type = $TransactionObj->Type; - next unless( $ConditionObj->ApplicableTransTypes =~ /(?:^|,)(?:Any|\Q$txn_type\E)(?:,|$)/i ); - # Load the scrip's Condition object - $ConditionObj->LoadCondition( - ScripObj => $self, - TicketObj => $args{'TicketObj'}, - TransactionObj => $TransactionObj, - ); + else { + $RT::Logger->error( "Unknown Scrip stage: '$stage'" ); + return (undef); + } + my $ConditionObj = $self->ConditionObj; + foreach my $TransactionObj ( @Transactions ) { + # in TxnBatch stage we can select scrips that are not applicable to all txns + my $txn_type = $TransactionObj->Type; + next unless( $ConditionObj->ApplicableTransTypes =~ /(?:^|,)(?:Any|\Q$txn_type\E)(?:,|$)/i ); + # Load the scrip's Condition object + $ConditionObj->LoadCondition( + ScripObj => $self, + TicketObj => $args{'TicketObj'}, + TransactionObj => $TransactionObj, + ); if ( $ConditionObj->IsApplicable() ) { - # We found an application Transaction -- return it + # We found an application Transaction -- return it $return = $TransactionObj; last; } - } + } }; if ($@) { @@ -444,9 +631,11 @@ sub Prepare { my $return; eval { - $self->ActionObj->LoadAction( ScripObj => $self, - TicketObj => $args{'TicketObj'}, - TransactionObj => $args{'TransactionObj'}, + $self->ActionObj->LoadAction( + ScripObj => $self, + TicketObj => $args{'TicketObj'}, + TransactionObj => $args{'TransactionObj'}, + TemplateObj => $self->TemplateObj( $args{'TicketObj'}->Queue ), ); $return = $self->ActionObj->Prepare(); @@ -508,8 +697,7 @@ sub _Set { ); unless ( $self->CurrentUserHasRight('ModifyScrips') ) { - $RT::Logger->debug( - "CurrentUser can't modify Scrips for " . $self->Queue . "\n" ); + $RT::Logger->debug( "CurrentUser can't modify Scrips" ); return ( 0, $self->loc('Permission Denied') ); } @@ -553,61 +741,22 @@ sub _Set { sub _Value { my $self = shift; - unless ( $self->CurrentUserHasRight('ShowScrips') ) { - $RT::Logger->debug( "CurrentUser can't modify Scrips for " - . $self->__Value('Queue') - . "\n" ); - return (undef); - } + return unless $self->CurrentUserHasRight('ShowScrips'); return $self->__Value(@_); } +=head2 ACLEquivalenceObjects - -=head2 CurrentUserHasRight - -Helper menthod for HasRight. Presets Principal to CurrentUser then -calls HasRight. - -=cut - -sub CurrentUserHasRight { - my $self = shift; - my $right = shift; - return ( $self->HasRight( Principal => $self->CurrentUser->UserObj, - Right => $right ) ); - -} - - - -=head2 HasRight - -Takes a param-hash consisting of "Right" and "Principal" Principal is -an RT::User object or an RT::CurrentUser object. "Right" is a textual -Right string that applies to Scrips. +Having rights on any of the queues the scrip applies to is equivalent to +having rights on the scrip. =cut -sub HasRight { +sub ACLEquivalenceObjects { my $self = shift; - my %args = ( Right => undef, - Principal => undef, - @_ ); - - if ( $self->SUPER::_Value('Queue') ) { - return $args{'Principal'}->HasRight( - Right => $args{'Right'}, - Object => $self->QueueObj - ); - } - else { - return $args{'Principal'}->HasRight( - Object => $RT::System, - Right => $args{'Right'}, - ); - } + return unless $self->id; + return @{ $self->AddedTo->ItemsArrayRef }; } @@ -699,7 +848,7 @@ sub SetTemplate { return ( 0, $self->loc( "Template '[_1]' not found", $value ) ) unless $template->Id; - return $self->_Set( Field => 'Template', Value => $template->Id ); + return $self->_Set( Field => 'Template', Value => $template->Name ); } 1; @@ -762,10 +911,10 @@ Returns the ScripCondition Object which has the id returned by ScripCondition =cut sub ScripConditionObj { - my $self = shift; - my $ScripCondition = RT::ScripCondition->new($self->CurrentUser); - $ScripCondition->Load($self->__Value('ScripCondition')); - return($ScripCondition); + my $self = shift; + my $ScripCondition = RT::ScripCondition->new($self->CurrentUser); + $ScripCondition->Load($self->__Value('ScripCondition')); + return($ScripCondition); } =head2 ScripAction @@ -794,48 +943,12 @@ Returns the ScripAction Object which has the id returned by ScripAction =cut sub ScripActionObj { - my $self = shift; - my $ScripAction = RT::ScripAction->new($self->CurrentUser); - $ScripAction->Load($self->__Value('ScripAction')); - return($ScripAction); + my $self = shift; + my $ScripAction = RT::ScripAction->new($self->CurrentUser); + $ScripAction->Load($self->__Value('ScripAction')); + return($ScripAction); } -=head2 ConditionRules - -Returns the current value of ConditionRules. -(In the database, ConditionRules is stored as text.) - - - -=head2 SetConditionRules VALUE - - -Set ConditionRules to VALUE. -Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -(In the database, ConditionRules will be stored as a text.) - - -=cut - - -=head2 ActionRules - -Returns the current value of ActionRules. -(In the database, ActionRules is stored as text.) - - - -=head2 SetActionRules VALUE - - -Set ActionRules to VALUE. -Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -(In the database, ActionRules will be stored as a text.) - - -=cut - - =head2 CustomIsApplicableCode Returns the current value of CustomIsApplicableCode. @@ -890,37 +1003,19 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =cut -=head2 Stage - -Returns the current value of Stage. -(In the database, Stage is stored as varchar(32).) - - - -=head2 SetStage VALUE - - -Set Stage to VALUE. -Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -(In the database, Stage will be stored as a varchar(32).) - - -=cut - - -=head2 Queue +=head2 Disabled -Returns the current value of Queue. -(In the database, Queue is stored as int(11).) +Returns the current value of Disabled. +(In the database, Disabled is stored as smallint(6).) -=head2 SetQueue VALUE +=head2 SetDisabled VALUE -Set Queue to VALUE. +Set Disabled to VALUE. Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -(In the database, Queue will be stored as a int(11).) +(In the database, Disabled will be stored as a smallint(6).) =cut @@ -929,7 +1024,7 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure. =head2 Template Returns the current value of Template. -(In the database, Template is stored as int(11).) +(In the database, Template is stored as varchar(200).) @@ -938,7 +1033,7 @@ Returns the current value of Template. Set Template to VALUE. Returns (1, 'Status message') on success and (0, 'Error Message') on failure. -(In the database, Template will be stored as a int(11).) +(In the database, Template will be stored as a varchar(200).) =cut @@ -985,41 +1080,85 @@ 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 => ''}, Description => - {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 => ''}, ScripCondition => - {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'}, ScripAction => - {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, - ConditionRules => - {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''}, - ActionRules => - {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''}, + {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'}, CustomIsApplicableCode => - {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''}, + {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''}, CustomPrepareCode => - {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''}, + {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''}, CustomCommitCode => - {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''}, - Stage => - {read => 1, write => 1, sql_type => 12, length => 32, is_blob => 0, is_numeric => 0, type => 'varchar(32)', default => ''}, - Queue => - {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 => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''}, + Disabled => + {read => 1, write => 1, sql_type => 5, length => 6, is_blob => 0, is_numeric => 1, type => 'smallint(6)', default => '0'}, Template => - {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 => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => 'Blank'}, 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 => ''}, } }; +sub FindDependencies { + my $self = shift; + my ($walker, $deps) = @_; + + $self->SUPER::FindDependencies($walker, $deps); + + my $applied = RT::ObjectScrips->new( $self->CurrentUser ); + $applied->LimitToScrip( $self->id ); + $deps->Add( in => $applied ); + + $deps->Add( out => $self->ScripConditionObj ); + $deps->Add( out => $self->ScripActionObj ); + $deps->Add( out => $self->TemplateObj ); +} + +sub __DependsOn { + my $self = shift; + my %args = ( + Shredder => undef, + Dependencies => undef, + @_, + ); + my $deps = $args{'Dependencies'}; + my $list = []; + + my $objs = RT::ObjectScrips->new( $self->CurrentUser ); + $objs->LimitToScrip( $self->Id ); + push @$list, $objs; + + $deps->_PushDependencies( + BaseObject => $self, + Flags => RT::Shredder::Constants::DEPENDS_ON, + TargetObjects => $list, + Shredder => $args{'Shredder'} + ); + + return $self->SUPER::__DependsOn( %args ); +} + +sub Serialize { + my $self = shift; + my %args = (@_); + my %store = $self->SUPER::Serialize(@_); + + # Store the string, not a reference to the object + $store{Template} = $self->Template; + + return %store; +} + RT::Base->_ImportOverlays(); 1; |