Custom Action's fail

I’m trying to implement a custom action & for some reason it keeps failing. I’m using the AdminConditionsAndActiions plug in for the registation of the module & I’m trying to implement SetCorresponderAsCC. I’ve made custom Conditions using the plugin and those work just fine.

I’ve made /opt/rt4/local/lib/RT/Action and inside I have SetCorresponderAsCC.pm

The current code I have is:


package RT::Action::SetCorresponderAsCC;
use base qw(RT::Action);
use strict;
use warnings;

sub Prepare {
return 1;
}

sub Commit {
$RT::Logger->debug(“Commit of script - set corresponder as cc”);
$RT::Logger->debug(“init actor”);
my $Actor = $self->TransactionObj->Creator;
RT::Logger->debug(“Init corresponderid”);
my $Corresponder_id = $self->TransactionObj->CreatorObj->PrincipalId;
$RT::Logger->debug(“init owner email”);
my $OwnerEmail = $self->TicketObj->OwnerObj->EmailAddress();
$RT::Logger->debug(“end script”);
return 1;
}

1;


If I remove all my code, and leave the debug lines the plug in works fine. If I execute exactly what is written, I get the following in the debug log:

[3423] [Tue May 2 17:01:16 2017] [error]: Scrip Prepare 36 died. - Require of RT::Action::SetCorresponderAsCC action module failed.
Global symbol “$self” requires explicit package name at /opt/rt4/sbin/…/local/lib/RT/Action/SetCorresponderAsCC.pm line 13.
Global symbol “$self” requires explicit package name at /opt/rt4/sbin/…/local/lib/RT/Action/SetCorresponderAsCC.pm line 15.
Global symbol “$self” requires explicit package name at /opt/rt4/sbin/…/local/lib/RT/Action/SetCorresponderAsCC.pm line 17.
Compilation failed in require at /opt/rt4/sbin/…/lib/RT/ScripAction.pm line 164.

Stack:
[/opt/rt4/sbin/…/lib/RT/ScripAction.pm:164]
[/opt/rt4/sbin/…/lib/RT/ScripAction.pm:164]

Inside RT under Admin → Global → Actions, my values are:
Name: Set Corresponder As CC
Description: Make the current Corresponder a permanent CC on the ticket
Action Module: SetCorresponderAsCC
Parameters to Pass: BLANK

I must be missing something obvious, but I can’t seem to find it. Can anyone please help?

I’ve finally had some time to comeback and revisit this Scrip. If I actually implement it as a “User defined” piece of code versus a module, the error messages changes to “the scrip didn’t prepare”. I saw that this error can occur with a malformed template, but I’m using the Blank template.

Is the code outdated? I’m not sure what’s happening.

I’ve discovered part of the problem. In the code, the way $Actor is initialized, the following code shouldn’t read $Actor->id as the initialization is giving you the ID. Right now, I’m working out hot to prevent the Owner of the ticket from being added as a permanent CC. I’ll post all my code once I’m finished, but I think I’m on the right track now.

Bottom line: Scrip coding takes lots of practice.

UPDATE!!! First; I went back and did everything through the web browser versus a custom action. I had to rewrite the script code but it works perfectly now. All the code lives in the “commit” section, so the next step is to break that apart as the test code can be separate. Regardless, this is the code for Set Corresponder As CC:


my $Actor = RT::User->new($RT::SystemUser);
my $Owner = $self->TicketObj->OwnerObj;
$Actor->Load($self->TransactionObj->Creator);
#========================================
# Did the system perform the update?
if ($Actor->id == $RT::SystemUser->id)
{
   $RT::Logger->debug("RT-DEBUG System made the update, don't add them");
   return 1;
}
$RT::Logger->debug("RT-DEBUG The system didn't make the update.");
#========================================================================
# Did the owner make the update?
if ($self->TicketObj->IsOwner($Actor))
{
   $RT::Logger->debug("RT-DEBUG Owner updated the ticket, exit");
   return 1;
}
$RT::Logger->debug("RT-DEBUG The owner didn't make the update.");
#========================================================================
# Did the/a Requestor make the update?
if ($self->TicketObj->IsRequestor($Actor->PrincipalId))
{
  $RT::Logger->debug("RT-DEBUG A Requestor updated, exit");
  return 1;
}
$RT::Logger->debug("RT-DEBUG Requestor didn't make the update.");
#========================================================================
# Did a CC make the update?
if ($self->TicketObj->IsCc($Actor->PrincipalId))
{
 $RT::Logger->debug("RT-DEBUG CC made the update, exit");
 return 1;
}
$RT::Logger->debug("RT-DEBUG CC didn't make the update.");
#========================================================================
# Did an AdminCC make the update?
if ($self->TicketObj->IsAdminCc($Actor->PrincipalId))
{
  $RT::Logger->debug("RT-DEBUG AdminCC made the update, exit");
  return 1;
}
$RT::Logger->debug("RT-DEBUG AdminCC didn't make the update.");
#========================================================================
# We've checked everyone, this person should be added.
my ($status, $msg) = $self->TicketObj->AddWatcher(
     Type => "Cc",
     PrincipalId => $Actor->PrincipalId);

unless ( $status ) 
{
  $RT::Logger->error("RT-DEBUG Couldn't add watcher: $msg");
  return 1;
}
#========================================================================
$RT::Logger->debug('RT-DEBUG User was added as a CC');

return 1;

However, when I move this to the .pm file I wrote, it fails again:


[5493] [Wed May 10 20:35:19 2017] [error]: Scrip Prepare 36 died. - Require of RT::Action::SetCorresponderAsCC action module failed.
Global symbol "$self" requires explicit package name at /opt/rt4/sbin/../local/lib/RT/Action/SetCorresponderAsCC.pm line 12.
Global symbol "$self" requires explicit package name at /opt/rt4/sbin/../local/lib/RT/Action/SetCorresponderAsCC.pm line 13.
Global symbol "$self" requires explicit package name at /opt/rt4/sbin/../local/lib/RT/Action/SetCorresponderAsCC.pm line 24.
Global symbol "$self" requires explicit package name at /opt/rt4/sbin/../local/lib/RT/Action/SetCorresponderAsCC.pm line 32.
Global symbol "$self" requires explicit package name at /opt/rt4/sbin/../local/lib/RT/Action/SetCorresponderAsCC.pm line 40.
Global symbol "$self" requires explicit package name at /opt/rt4/sbin/../local/lib/RT/Action/SetCorresponderAsCC.pm line 48.
Global symbol "$self" requires explicit package name at /opt/rt4/sbin/../local/lib/RT/Action/SetCorresponderAsCC.pm line 56.
Compilation failed in require at /opt/rt4/sbin/../lib/RT/ScripAction.pm line 164.

I’d like to use the .pm files to help keep my code portable. What am I overlooking? I’ve made good progress!! :slight_smile:

UPDATE!!! I found the issue, but I don’t understand why.

I started re-reading the documentation included in: RT::Extension::AdminConditionsAndActions - Admin Conditions And Actions - metacpan.org

So I decided to take a look at some of the predefined modules that came with RT. I noticed one major difference:

my $self = shift;

was the first line of each sub. I added those lines to the Prepare and Commit function calls & my module now works! I found this on the Perl site: shift - Perldoc Browser but I don’t see why its required. Why do I need to execute this command before anything else?

Regardless, it looks like the module now works as expected! Any comments/replies would be appreciated.

Below is the completed code for the SetCorresponderAsCC.pm:


package RT::Action::SetCorresponderAsCC;
use base 'RT::Action';
use strict;
use warnings;

sub Prepare {
	my $self = shift;
	return 1;
}

sub Commit {
my $self = shift;
my $Actor = RT::User->new($RT::SystemUser);
my $Owner = $self->TicketObj->OwnerObj;
$Actor->Load($self->TransactionObj->Creator);
#========================================================================
# Did the system perform the update?
if ($Actor->id == $RT::SystemUser->id)
{
   $RT::Logger->debug("RT-DEBUG System made the update, don't add them");
   return 1;
}
$RT::Logger->debug("RT-DEBUG The system didn't make the update.");
#========================================================================
# Did the owner make the update?
if ($self->TicketObj->IsOwner($Actor))
{
   $RT::Logger->debug("RT-DEBUG Owner updated the ticket, exit");
   return 1;
}
$RT::Logger->debug("RT-DEBUG The owner didn't make the update.");
#========================================================================
# Did the/a Requestor make the update?
if ($self->TicketObj->IsRequestor($Actor->PrincipalId))
{
  $RT::Logger->debug("RT-DEBUG A Requestor updated, exit");
  return 1;
}
$RT::Logger->debug("RT-DEBUG Requestor didn't make the update.");
#========================================================================
# Did a CC make the update?
if ($self->TicketObj->IsCc($Actor->PrincipalId))
{
 $RT::Logger->debug("RT-DEBUG CC made the update, exit");
 return 1;
}
$RT::Logger->debug("RT-DEBUG CC didn't make the update.");
#========================================================================
# Did an AdminCC make the update?
if ($self->TicketObj->IsAdminCc($Actor->PrincipalId))
{
  $RT::Logger->debug("RT-DEBUG AdminCC made the update, exit");
  return 1;
}
$RT::Logger->debug("RT-DEBUG AdminCC didn't make the update.");
#========================================================================
# We've checked everyone, this person should be added.
my ($status, $msg) = $self->TicketObj->AddWatcher(
     Type => "Cc",
     PrincipalId => $Actor->PrincipalId);

unless ( $status ) 
{
  $RT::Logger->error("RT-DEBUG Couldn't add watcher: $msg");
  return 1;
}
#========================================================================
$RT::Logger->debug('RT-DEBUG User was added as a CC');

return 1;
}

1;

Perl doesn’t automatically set up the identifier for the object like a lot of languages do. The way perl gets an object in to a subroutine is by passing it as the first argument. In perl, subroutine arguments are passed in the @_ array, and shift() removes and returns the first element in an array, defaulting to @_ as the array to operate on if it is not specified. So a more explicit way to write that line of code would be:

my $self = shift( @_ );

https://perldoc.perl.org/perlobj.html#A-Method-is-Simply-a-Subroutine

Todd - Thank you for the explanation. I don’t get to code in Perl often so some of these things are lost on me. I’m also spread so thin at my admin job I only have one side, so it’s hard to focus. I appreciate the clarification!!