+sub LoadGeneratedData {
+ my $class = shift;
+ my $pm_path = ( File::Spec->splitpath( $INC{'RT.pm'} ) )[1];
+
+ require "$pm_path/RT/Generated.pm" || die "Couldn't load RT::Generated: $@";
+ $class->CanonicalizeGeneratedPaths();
+}
+
+sub CanonicalizeGeneratedPaths {
+ my $class = shift;
+ unless ( File::Spec->file_name_is_absolute($EtcPath) ) {
+
+ # if BasePath exists and is absolute, we won't infer it from $INC{'RT.pm'}.
+ # otherwise RT.pm will make the source dir(where we configure RT) be the
+ # BasePath instead of the one specified by --prefix
+ unless ( -d $BasePath
+ && File::Spec->file_name_is_absolute($BasePath) )
+ {
+ my $pm_path = ( File::Spec->splitpath( $INC{'RT.pm'} ) )[1];
+
+ # need rel2abs here is to make sure path is absolute, since $INC{'RT.pm'}
+ # is not always absolute
+ $BasePath = File::Spec->rel2abs(
+ File::Spec->catdir( $pm_path, File::Spec->updir ) );
+ }
+
+ $BasePath = Cwd::realpath($BasePath);
+
+ for my $path (
+ qw/EtcPath BinPath SbinPath VarPath LocalPath StaticPath LocalEtcPath
+ LocalLibPath LexiconPath LocalLexiconPath PluginPath FontPath
+ LocalPluginPath LocalStaticPath MasonComponentRoot MasonLocalComponentRoot
+ MasonDataDir MasonSessionDir/
+ )
+ {
+ no strict 'refs';
+
+ # just change relative ones
+ $$path = File::Spec->catfile( $BasePath, $$path )
+ unless File::Spec->file_name_is_absolute($$path);
+ }
+ }
+
+}
+
+=head2 AddJavaScript
+
+Helper method to add JS files to the C<@JSFiles> config at runtime.
+
+To add files, you can add the following line to your extension's main C<.pm>
+file:
+
+ RT->AddJavaScript( 'foo.js', 'bar.js' );
+
+Files are expected to be in a static root in a F<js/> directory, such as
+F<static/js/> in your extension or F<local/static/js/> for local overlays.
+
+=cut
+
+sub AddJavaScript {
+ my $self = shift;
+
+ my @old = RT->Config->Get('JSFiles');
+ RT->Config->Set( 'JSFiles', @old, @_ );
+ return RT->Config->Get('JSFiles');
+}
+
+=head2 AddStyleSheets
+
+Helper method to add CSS files to the C<@CSSFiles> config at runtime.
+
+To add files, you can add the following line to your extension's main C<.pm>
+file:
+
+ RT->AddStyleSheets( 'foo.css', 'bar.css' );
+
+Files are expected to be in a static root in a F<css/> directory, such as
+F<static/css/> in your extension or F<local/static/css/> for local
+overlays.
+
+=cut
+
+sub AddStyleSheets {
+ my $self = shift;
+ my @old = RT->Config->Get('CSSFiles');
+ RT->Config->Set( 'CSSFiles', @old, @_ );
+ return RT->Config->Get('CSSFiles');
+}
+
+=head2 JavaScript
+
+helper method of RT->Config->Get('JSFiles')
+
+=cut
+
+sub JavaScript {
+ return RT->Config->Get('JSFiles');
+}
+
+=head2 StyleSheets
+
+helper method of RT->Config->Get('CSSFiles')
+
+=cut
+
+sub StyleSheets {
+ return RT->Config->Get('CSSFiles');
+}
+
+=head2 Deprecated
+
+Notes that a particular call path is deprecated, and will be removed in
+a particular release. Puts a warning in the logs indicating such, along
+with a stack trace.
+
+Optional arguments include:
+
+=over
+
+=item Remove
+
+The release which is slated to remove the method or component
+
+=item Instead
+
+A suggestion of what to use in place of the deprecated API
+
+=item Arguments
+
+Used if not the entire method is being removed, merely a manner of
+calling it; names the arguments which are deprecated.
+
+=item Message
+
+Overrides the auto-built phrasing of C<Calling function ____ is
+deprecated> with a custom message.
+
+=item Object
+
+An L<RT::Record> object to print the class and numeric id of. Useful if the
+admin will need to hunt down a particular object to fix the deprecation
+warning.
+
+=back
+
+=cut
+
+sub Deprecated {
+ my $class = shift;
+ my %args = (
+ Arguments => undef,
+ Remove => undef,
+ Instead => undef,
+ Message => undef,
+ Stack => 1,
+ LogLevel => "warn",
+ @_,
+ );
+
+ my ($function) = (caller(1))[3];
+ my $stack;
+ if ($function eq "HTML::Mason::Commands::__ANON__") {
+ eval { HTML::Mason::Exception->throw() };
+ my $error = $@;
+ my $info = $error->analyze_error;
+ $function = "Mason component ".$info->{frames}[0]->filename;
+ $stack = join("\n", map { sprintf("\t[%s:%d]", $_->filename, $_->line) } @{$info->{frames}});
+ } else {
+ $function = "function $function";
+ $stack = Carp::longmess();
+ }
+ $stack =~ s/^.*?\n//; # Strip off call to ->Deprecated
+
+ my $msg;
+ if ($args{Message}) {
+ $msg = $args{Message};
+ } elsif ($args{Arguments}) {
+ $msg = "Calling $function with $args{Arguments} is deprecated";
+ } else {
+ $msg = "The $function is deprecated";
+ }
+ $msg .= ", and will be removed in RT $args{Remove}"
+ if $args{Remove};
+ $msg .= ".";
+
+ $msg .= " You should use $args{Instead} instead."
+ if $args{Instead};
+
+ $msg .= sprintf " Object: %s #%d.", blessed($args{Object}), $args{Object}->id
+ if $args{Object};
+
+ $msg .= " Call stack:\n$stack" if $args{Stack};
+
+ my $loglevel = $args{LogLevel};
+ RT->Logger->$loglevel($msg);
+}