+ my $action = $params{action} || 'dispatch';
+
+ my $script;
+ if ($controller =~ m/\.pl$/) {
+ # Old-style controller
+ $script = $controller;
+ } else {
+ $params{action} = "${controller}/${action}";
+ $script = "controller.pl";
+ }
+
+ my $query = join '&', map { uri_encode($_->[0]) . '=' . uri_encode($_->[1]) } @{ flatten(\%params) };
+
+ return "${script}?${query}";
+}
+
+sub redirect_to {
+ my $self = shift;
+ my $url = $self->url_for(@_);
+
+ if ($self->delay_flash_on_redirect) {
+ require SL::Helper::Flash;
+ SL::Helper::Flash::delay_flash();
+ }
+
+ print $::request->{cgi}->redirect($url);
+}
+
+sub render {
+ my $self = shift;
+ my $template = shift;
+ my ($options, %locals) = (@_ && ref($_[0])) ? @_ : ({ }, @_);
+
+ $options->{type} = lc($options->{type} || 'html');
+ $options->{no_layout} = 1 if $options->{type} eq 'js';
+
+ my $source;
+ if ($options->{inline}) {
+ $source = \$template;
+
+ } elsif($options->{raw}) {
+ $source = $template;
+
+ } else {
+ $source = "templates/webpages/${template}." . $options->{type};
+ croak "Template file ${source} not found" unless -f $source;
+ }
+
+ if (!$options->{partial} && !$options->{inline} && !$::form->{header}) {
+ if ($options->{no_layout}) {
+ $::form->{header} = 1;
+ my $content_type = $options->{type} eq 'js' ? 'text/javascript' : 'text/html';
+
+ print $::form->create_http_response(content_type => $content_type,
+ charset => $::lx_office_conf{system}->{dbcharset} || Common::DEFAULT_CHARSET());
+
+ } else {
+ $::form->{title} = $locals{title} if $locals{title};
+ $::form->header;
+ }
+ }
+
+ my %params = ( %locals,
+ AUTH => $::auth,
+ FLASH => $::form->{FLASH},
+ FORM => $::form,
+ INSTANCE_CONF => $::instance_conf,
+ LOCALE => $::locale,
+ LXCONFIG => \%::lx_office_conf,
+ LXDEBUG => $::lxdebug,
+ MYCONFIG => \%::myconfig,
+ SELF => $self,
+ );
+
+ my $output;
+ if (!$options->{raw}) {
+ my $parser = $self->_template_obj;
+ $parser->process($source, \%params, \$output) || croak $parser->error;
+ } else {
+ $output = $$source;
+ }
+
+ print $output unless $options->{inline} || $options->{no_output};
+
+ return $output;
+}
+
+sub send_file {
+ my ($self, $file_name, %params) = @_;
+
+ my $file = IO::File->new($file_name, 'r') || croak("Cannot open file '${file_name}'");
+ my $content_type = $params{type} || 'application/octet_stream';
+ my $attachment_name = $params{name} || $file_name;
+ $attachment_name =~ s:.*//::g;
+
+ print $::form->create_http_response(content_type => $content_type,
+ content_disposition => 'attachment; filename="' . $attachment_name . '"',
+ content_length => -s $file);
+
+ $::locale->with_raw_io(\*STDOUT, sub { print while <$file> });
+ $file->close;
+}
+
+#
+# Before/after run hooks
+#
+
+sub run_before {
+ _add_hook('before', @_);
+}
+
+sub run_after {
+ _add_hook('after', @_);
+}
+
+my %hooks;
+
+sub _add_hook {
+ my ($when, $class, $sub, %params) = @_;
+
+ foreach my $key (qw(only except)) {
+ $params{$key} = { map { ( $_ => 1 ) } @{ $params{$key} } } if $params{$key};
+ }