$::request: Funktionen "is_ajax()" und "type()"
authorMoritz Bunkus <m.bunkus@linet-services.de>
Wed, 6 Feb 2013 11:13:45 +0000 (12:13 +0100)
committerMoritz Bunkus <m.bunkus@linet-services.de>
Wed, 6 Feb 2013 11:19:09 +0000 (12:19 +0100)
SL/Dispatcher.pm
SL/Presenter.pm
SL/Request.pm
locale/de/all

index 44631a0..5282369 100644 (file)
@@ -35,7 +35,6 @@ use SL::Form;
 use SL::Helper::DateTime;
 use SL::InstanceConfiguration;
 use SL::Template::Plugin::HTMLFixes;
-use SL::Layout::None;
 
 # Trailing new line is added so that Perl will not add the line
 # number 'die' was called in.
@@ -69,6 +68,10 @@ sub pre_request_checks {
       show_error('login_screen/auth_db_unreachable');
     }
   }
+
+  if ($::request->type !~ m/^ (?: html | js | json ) $/x) {
+    die $::locale->text("Invalid request type '#1'", $::request->type);
+  }
 }
 
 sub show_error {
@@ -182,17 +185,21 @@ sub handle_request {
   $::locale        = Locale->new($::lx_office_conf{system}->{language});
   $::form          = Form->new;
   $::instance_conf = SL::InstanceConfiguration->new;
-  $::request       = {
+  $::request       = SL::Request->new(
     cgi => CGI->new({}),
     layout => SL::Layout::None->new,
-  };
+  );
 
   my $session_result = $::auth->restore_session;
   $::auth->create_or_refresh_session;
 
   $::form->read_cgi_input;
 
-  eval { ($routing_type, $script_name, $action) = _route_request($ENV{SCRIPT_NAME}); 1; } or return;
+  my %routing;
+  eval { %routing = _route_request($ENV{SCRIPT_NAME}); 1; } or return;
+  ($routing_type, $script_name, $action) = @routing{qw(type controller action)};
+
+  $::request->type(lc($routing{request_type} || 'html'));
 
   if ($routing_type eq 'old') {
     $::form->{action}  =  lc $::form->{action};
@@ -312,9 +319,9 @@ sub _interface_is_fcgi {
 sub _route_request {
   my $script_name = shift;
 
-  return $script_name =~ m/dispatcher\.pl$/ ? ('old',        _route_dispatcher_request())
-       : $script_name =~ m/controller\.pl/  ? ('controller', _route_controller_request())
-       :                                      ('old',        $script_name, $::form->{action});
+  return $script_name =~ m/dispatcher\.pl$/ ? (type => 'old',        _route_dispatcher_request())
+       : $script_name =~ m/controller\.pl/  ? (type => 'controller', _route_controller_request())
+       :                                      (type => 'old',        controller => $script_name, action => $::form->{action});
 }
 
 sub _route_dispatcher_request {
@@ -344,24 +351,26 @@ sub _route_dispatcher_request {
     show_error('generic/error');
   };
 
-  return ($script_name, $action);
+  return (controller => $script_name, action => $action);
 }
 
 sub _route_controller_request {
-  my ($controller, $action);
+  my ($controller, $action, $request_type);
 
   eval {
-    $::form->{action}      =~ m|^ ( [A-Z] [A-Za-z0-9_]* ) / ( [a-z] [a-z0-9_]* ) $|x || die "Unroutable request -- inavlid controller/action.\n";
+    $::form->{action}      =~ m|^ ( [A-Z] [A-Za-z0-9_]* ) / ( [a-z] [a-z0-9_]* ) ( \. [a-zA-Z]+ )? $|x || die "Unroutable request -- inavlid controller/action.\n";
     ($controller, $action) =  ($1, $2);
     delete $::form->{action};
 
+    $request_type = $3 ? lc(substr($3, 1)) : 'html';
+
     1;
   } or do {
     $::form->{label_error} = $::request->{cgi}->pre($EVAL_ERROR);
     show_error('generic/error');
   };
 
-  return ($controller, $action);
+  return (controller => $controller, action => $action, request_type => $request_type);
 }
 
 sub _cache_file_modification_times {
index 68ef8c8..6658184 100644 (file)
@@ -16,8 +16,7 @@ use SL::Presenter::Project;
 use SL::Presenter::Record;
 
 sub get {
-  $::request->{presenter} ||= SL::Presenter->new;
-  return $::request->{presenter};
+  return $::request->presenter;
 }
 
 sub render {
index 6dfff71..5a840a6 100644 (file)
@@ -2,14 +2,45 @@ package SL::Request;
 
 use strict;
 
-use SL::Common;
-use SL::MoreCommon qw(uri_encode uri_decode);
+use parent qw(Rose::Object);
+
+use CGI qw(-no_xhtml);
 use List::Util qw(first max min sum);
 use List::MoreUtils qw(all any apply);
 use Exporter qw(import);
 
+use SL::Common;
+use SL::MoreCommon qw(uri_encode uri_decode);
+use SL::Layout::None;
+use SL::Presenter;
+
 our @EXPORT_OK = qw(flatten unflatten read_cgi_input);
 
+use Rose::Object::MakeMethods::Generic
+(
+  'scalar --get_set_init' => [ qw(cgi layout presenter is_ajax type) ],
+);
+
+sub init_cgi {
+  return CGI->new({});
+}
+
+sub init_layout {
+  return SL::Layout::None->new;
+}
+
+sub init_presenter {
+  return SL::Presenter->new;
+}
+
+sub init_is_ajax {
+  return ($ENV{HTTP_X_REQUESTED_WITH} || '') eq 'XMLHttpRequest' ? 1 : 0;
+}
+
+sub init_type {
+  return 'html';
+}
+
 sub _store_value {
   my ($target, $key, $value) = @_;
   my @tokens = split /((?:\[\+?\])?(?:\.)|(?:\[\+?\]))/, $key;
@@ -322,12 +353,13 @@ __END__
 
 =head1 NAME
 
-SL::Request.pm - request parsing and data serialization
+SL::Request.pm - request parsing, data serialization, request information
 
 =head1 SYNOPSIS
 
-This module handles unpacking of cgi parameters. usually you don't want to call
-anything in here directly.
+This module handles unpacking of CGI parameters. It also gives
+information about the request like whether or not it was done via AJAX
+or the requested content type.
 
   use SL::Request qw(read_cgi_input);
 
@@ -338,10 +370,19 @@ anything in here directly.
   my $new_arrayref = flatten($hashref);
   my $new_hashref  = unflatten($new_arrayref);
 
+  # Handle AJAX requests differently than normal requests:
+  if ($::request->is_ajax) {
+    $controller->render('json-mask', { type => 'json' });
+  } else {
+    $controller->render('full-mask');
+  }
 
 =head1 DESCRIPTION
 
-This module handles flattening and unflattening of data for request
+This module provides information about the request made by the
+browser.
+
+It also handles flattening and unflattening of data for request
 roundtrip purposes. kivitendo uses the format as described below:
 
 =over 4
@@ -472,6 +513,15 @@ Return value is the flattened array ref.
 
 This function will parse the array ref, and will store the contents into the hash ref. The hash ref may be non empty, in this case any new keys will override the old ones only on leafs with same type. Type changes on a node will die.
 
+=item C<is_ajax>
+
+Returns trueish if the request is an XML HTTP request, also known as
+an 'AJAX' request.
+
+=item C<type>
+
+Returns the requested content type (either C<html>, C<js> or C<json>).
+
 =back
 
 =head1 SPECIAL FUNCTIONS
index 290e33d..b05f929 100644 (file)
@@ -1026,6 +1026,7 @@ $self->{texts} = {
   'Invalid'                     => 'Ungültig',
   'Invalid follow-up ID.'       => 'Ung&uuml;ltige Wiedervorlage-ID.',
   'Invalid quantity.'           => 'Die Mengenangabe ist ung&uuml;ltig.',
+  'Invalid request type \'#1\'' => '',
   'Invdate'                     => 'Rechnungsdatum',
   'Invdate from'                => 'Rechnungen von',
   'Inventory'                   => 'Inventar',