How to add runmodes to a CGI::Application

There really are a ton of messy ways to tinker with adding runmodes to CGI::Application.

I tried a lot of different things, succesfully, strangely, even ‘cleverly’.

If you have a plugin that is being ‘use’d, you should have an import function.

Via Callback

package CGI::Application::Plugin::Cakes;
use strict;
use Exporter;
use vars qw(@EXPORT @ISA);
@EXPORT = qw(view_cakes _find_cakes find_old_cakes);
@ISA = qw/Exporter/;

sub import {
   my $caller = scalar(caller);
   $caller->add_callback( 'init', \&_register_runmodes );
   goto &Exporter::import;
}
sub _register_runmodes {
   my $self = shift;
   $self->run_modes([qw(view_cakes find_old_cakes)]);
}

sub view_cakes {
   my $self = shift;
   return 'Cakes...';
}

sub find_old_cakes {
   my $self = shift;
   my $cakes = $self->_find_cakes;
   return "Cakes... @$cakes";
}

sub _find_cakes {
   my $self = shift;
   return [qw(strawberry vanilla raspberry)];
}

Now, what is most crucial here is the import function.. You can also write the same as above in this alternate way:

sub import {
   my $caller = scalar(caller);
   $caller->add_callback(
      'init',
      sub {
         my $self = shift;
         $self->run_modes([qw(view_cakes find_old_cakes)]);
      },
   );
   goto &Exporter::import;
}

Now, keep in mind, this is not a callback tutorial. But essentially, the syntax is

$YOUR_CGIAPP_CLASS->add_callback( $STAGE_IN_CGIAPP, $REF_TO_METHOD );

Now, what confused me a lot, was that you can make this be a class method or an object method.
ANd I felt like if I did a class method, I could not affect my object! Right? Actually, wrong. You can set callbacks at the class level, which will run for the object. Notice that view_cakes and find_old_cakes are object methods, but we inserted a callback to the class.

Why init instead of prerun?
If you add a callback hook to init, the runmodes will be available before you run() the instance.
This may be desirable for testing. Or maybe you have a self generating option menu, that reads the runmodes and offers them as links… hmmm….

What is the class?
The class is the package that defines your CGI::Application, where you have
package My::App;
use base 'CGI::Application';
.

Jesse Erlbaum code helped me figure this out.