+=head2 SetType
+
+If setting Type to Perl, require the ExecuteCode right.
+
+=cut
+
+sub SetType {
+ my $self = shift;
+ my $NewType = shift;
+
+ if ($NewType eq 'Perl' && !$self->CurrentUser->HasRight(Right => 'ExecuteCode', Object => $RT::System)) {
+ return ( undef, $self->loc('Permission Denied') );
+ }
+
+ return $self->_Set( Field => 'Type', Value => $NewType );
+}
+
+=head2 SetContent
+
+If changing content and the type is Perl, require the ExecuteCode right.
+
+=cut
+
+sub SetContent {
+ my $self = shift;
+ my $NewContent = shift;
+
+ if ($self->Type eq 'Perl' && !$self->CurrentUser->HasRight(Right => 'ExecuteCode', Object => $RT::System)) {
+ return ( undef, $self->loc('Permission Denied') );
+ }
+
+ return $self->_Set( Field => 'Content', Value => $NewContent );
+}
+
+sub _UpdateAttributes {
+ my $self = shift;
+ my %args = (
+ NewValues => {},
+ @_,
+ );
+
+ my $type = $args{NewValues}{Type} || $self->Type;
+
+ # forbid updating content when the (possibly new) value of Type is Perl
+ if ($type eq 'Perl' && exists $args{NewValues}{Content}) {
+ if (!$self->CurrentUser->HasRight(Right => 'ExecuteCode', Object => $RT::System)) {
+ return $self->loc('Permission Denied');
+ }
+ }
+
+ return $self->SUPER::_UpdateAttributes(%args);
+}
+
+=head2 CompileCheck
+
+If the template's Type is Perl, then compile check all the codeblocks to see if
+they are syntactically valid. We eval them in a codeblock to avoid actually
+executing the code.
+
+Returns an (ok, message) pair.
+
+=cut
+
+sub CompileCheck {
+ my $self = shift;
+
+ return (1, $self->loc("Template does not include Perl code"))
+ unless $self->Type eq 'Perl';
+
+ my $content = $self->Content;
+ $content = '' if !defined($content);
+
+ my $template = Text::Template->new(
+ TYPE => 'STRING',
+ SOURCE => $content,
+ );
+ my ($ok) = $template->compile;
+ return ( undef, $self->loc('Template parsing error: [_1]', $Text::Template::ERROR) ) if !$ok;
+
+ # copied from Text::Template::fill_in and refactored to be compile checks
+ foreach my $fi_item (@{$template->{SOURCE}}) {
+ my ($fi_type, $fi_text, $fi_lineno) = @$fi_item;
+ next unless $fi_type eq 'PROG';
+
+ do {
+ no strict 'vars';
+ eval "sub { $fi_text }";
+ };
+ next if !$@;
+
+ my $error = $@;
+
+ # provide a (hopefully) useful line number for the error, but clean up
+ # all the other extraneous garbage
+ $error =~ s/\(eval \d+\) line (\d+).*/"template line " . ($1+$fi_lineno-1)/es;
+
+ return (0, $self->loc("Couldn't compile template codeblock '[_1]': [_2]", $fi_text, $error));
+ }
+
+ return (1, $self->loc("Template compiles"));
+}
+
+=head2 CurrentUserCanRead
+
+=cut
+
+sub CurrentUserCanRead {
+ my $self =shift;
+
+ return 1 if $self->CurrentUserHasQueueRight('ShowTemplate');
+
+ return $self->CurrentUser->HasRight( Right =>'ShowGlobalTemplates', Object => $RT::System )
+ if !$self->QueueObj->Id;
+
+ return;
+}
+
+1;
+
+use RT::Queue;
+use base 'RT::Record';
+
+sub Table {'Templates'}
+
+
+
+
+
+
+=head2 id
+
+Returns the current value of id.
+(In the database, id is stored as int(11).)
+
+
+=cut
+
+
+=head2 Queue
+
+Returns the current value of Queue.
+(In the database, Queue is stored as int(11).)
+
+
+
+=head2 SetQueue VALUE
+
+
+Set Queue 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).)
+
+
+=cut
+
+
+=head2 QueueObj
+
+Returns the Queue Object which has the id returned by Queue
+
+
+=cut
+
+sub QueueObj {
+ my $self = shift;
+ my $Queue = RT::Queue->new($self->CurrentUser);
+ $Queue->Load($self->__Value('Queue'));
+ return($Queue);
+}
+
+=head2 Name
+
+Returns the current value of Name.
+(In the database, Name is stored as varchar(200).)
+
+
+
+=head2 SetName VALUE
+
+
+Set Name to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, Name will be stored as a varchar(200).)
+
+
+=cut
+
+
+=head2 Description
+
+Returns the current value of Description.
+(In the database, Description is stored as varchar(255).)
+
+
+
+=head2 SetDescription VALUE
+
+
+Set Description to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, Description will be stored as a varchar(255).)
+
+
+=cut
+
+
+=head2 Type
+
+Returns the current value of Type.
+(In the database, Type is stored as varchar(16).)
+
+
+
+=head2 SetType VALUE
+
+
+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(16).)
+
+
+=cut
+
+
+=head2 Language
+
+Returns the current value of Language.
+(In the database, Language is stored as varchar(16).)
+
+
+
+=head2 SetLanguage VALUE
+
+
+Set Language to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, Language will be stored as a varchar(16).)
+
+
+=cut
+
+
+=head2 TranslationOf
+
+Returns the current value of TranslationOf.
+(In the database, TranslationOf is stored as int(11).)
+
+
+
+=head2 SetTranslationOf VALUE
+
+
+Set TranslationOf to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, TranslationOf will be stored as a int(11).)
+
+
+=cut
+
+
+=head2 Content
+
+Returns the current value of Content.
+(In the database, Content is stored as text.)
+
+
+
+=head2 SetContent VALUE
+
+
+Set Content to VALUE.
+Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
+(In the database, Content will be stored as a text.)
+
+
+=cut
+
+
+=head2 LastUpdated
+
+Returns the current value of LastUpdated.
+(In the database, LastUpdated is stored as datetime.)
+
+
+=cut
+
+
+=head2 LastUpdatedBy
+
+Returns the current value of LastUpdatedBy.
+(In the database, LastUpdatedBy is stored as int(11).)
+
+
+=cut
+
+
+=head2 Creator
+
+Returns the current value of Creator.
+(In the database, Creator is stored as int(11).)
+
+
+=cut
+
+
+=head2 Created
+
+Returns the current value of Created.
+(In the database, Created is stored as datetime.)
+
+
+=cut
+
+
+
+sub _CoreAccessible {
+ {
+
+ id =>
+ {read => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => ''},
+ Queue =>
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
+ Name =>
+ {read => 1, write => 1, sql_type => 12, length => 200, is_blob => 0, is_numeric => 0, type => 'varchar(200)', default => ''},
+ Description =>
+ {read => 1, write => 1, sql_type => 12, length => 255, is_blob => 0, is_numeric => 0, type => 'varchar(255)', default => ''},
+ Type =>
+ {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''},
+ Language =>
+ {read => 1, write => 1, sql_type => 12, length => 16, is_blob => 0, is_numeric => 0, type => 'varchar(16)', default => ''},
+ TranslationOf =>
+ {read => 1, write => 1, sql_type => 4, length => 11, is_blob => 0, is_numeric => 1, type => 'int(11)', default => '0'},
+ Content =>
+ {read => 1, write => 1, sql_type => -4, length => 0, is_blob => 1, is_numeric => 0, type => 'text', default => ''},
+ LastUpdated =>
+ {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'},
+ Creator =>
+ {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 => ''},
+
+ }
+};
+
+RT::Base->_ImportOverlays();
+