auf Original-Version zurückgesetzt
[kivitendo-erp.git] / SL / Layout / Base.pm
index 2212f71..c64a99a 100644 (file)
@@ -3,11 +3,12 @@ package SL::Layout::Base;
 use strict;
 use parent qw(Rose::Object);
 
 use strict;
 use parent qw(Rose::Object);
 
+use File::Slurp qw(read_file);
 use List::MoreUtils qw(uniq);
 use Time::HiRes qw();
 
 use Rose::Object::MakeMethods::Generic (
 use List::MoreUtils qw(uniq);
 use Time::HiRes qw();
 
 use Rose::Object::MakeMethods::Generic (
-  'scalar --get_set_init' => [ qw(menu auto_reload_resources_param) ],
+  'scalar --get_set_init' => [ qw(menu auto_reload_resources_param sub_layouts_by_name) ],
   'scalar'                => qw(focus),
   'array'                 => [
     'add_stylesheets_inline' => { interface => 'add', hash_key => 'stylesheets_inline' },
   'scalar'                => qw(focus),
   'array'                 => [
     'add_stylesheets_inline' => { interface => 'add', hash_key => 'stylesheets_inline' },
@@ -19,6 +20,7 @@ use Rose::Object::MakeMethods::Generic (
 
 use SL::Menu;
 use SL::Presenter;
 
 use SL::Menu;
 use SL::Presenter;
+use SL::System::Process;
 
 my %menu_cache;
 
 
 my %menu_cache;
 
@@ -29,12 +31,44 @@ sub new {
 }
 
 sub init_menu {
 }
 
 sub init_menu {
-  Menu->new('menu.ini');
+  SL::Menu->new('user');
+}
+
+sub init_sublayouts_by_name {
+  {}
+}
+
+sub webpages_path {
+  "templates/webpages";
+}
+
+sub get {
+  $_[0]->sub_layouts;
+  return grep { $_ } ($_[0]->sub_layouts_by_name->{$_[1]});
 }
 
 sub init_auto_reload_resources_param {
 }
 
 sub init_auto_reload_resources_param {
-  return '' unless $::lx_office_conf{debug}->{auto_reload_resources};
-  return sprintf('?rand=%d-%d-%d', Time::HiRes::gettimeofday(), int(rand 1000000000000));
+  if ($::lx_office_conf{debug}->{auto_reload_resources}) {
+    return sprintf('?rand=%d-%d-%d', Time::HiRes::gettimeofday(), int(rand 1000000000000));
+  }
+
+  if ($::lx_office_conf{debug}{git_commit_reload_resources}) {
+    my $git_dir = SL::System::Process::exe_dir() . '/.git';
+
+    return '' unless -d $git_dir;
+
+    my $content = eval { scalar(read_file($git_dir . '/HEAD')) };
+
+    return '' unless ($content // '') =~ m{\Aref: ([^\r\n]+)};
+
+    $content = eval { scalar(read_file($git_dir . '/' . $1)) };
+
+    return '' unless ($content // '') =~ m{\A([0-9a-fA-F]+)};
+
+    return '?rand=' . $1;
+  }
+
+  return '';
 }
 
 ##########################################
 }
 
 ##########################################
@@ -69,11 +103,16 @@ sub javascripts_inline {
 
 sub init_sub_layouts { [] }
 
 
 sub init_sub_layouts { [] }
 
+sub init_sub_layouts_by_name { +{} }
+
 
 #########################################
 
 #########################################
-# Interface
+# Stylesheets
 ########################################
 
 ########################################
 
+# override in sub layouts
+sub static_stylesheets {}
+
 sub add_stylesheets {
   &use_stylesheet;
 }
 sub add_stylesheets {
   &use_stylesheet;
 }
@@ -81,7 +120,7 @@ sub add_stylesheets {
 sub use_stylesheet {
   my $self = shift;
   push @{ $self->{stylesheets} ||= [] }, @_ if @_;
 sub use_stylesheet {
   my $self = shift;
   push @{ $self->{stylesheets} ||= [] }, @_ if @_;
-  @{ $self->{stylesheets} ||= [] };
+    (map { $_->use_stylesheet } $self->sub_layouts), $self->static_stylesheets, @{ $self->{stylesheets} ||= [] };
 }
 
 sub stylesheets {
 }
 
 sub stylesheets {
@@ -89,7 +128,7 @@ sub stylesheets {
   my $css_path = $self->get_stylesheet_for_user;
 
   return uniq grep { $_ } map { $self->_find_stylesheet($_, $css_path)  }
   my $css_path = $self->get_stylesheet_for_user;
 
   return uniq grep { $_ } map { $self->_find_stylesheet($_, $css_path)  }
-    $self->use_stylesheet, map { $_->stylesheets } $self->sub_layouts;
+    $self->use_stylesheet;
 }
 
 sub _find_stylesheet {
 }
 
 sub _find_stylesheet {
@@ -98,12 +137,13 @@ sub _find_stylesheet {
   return "$css_path/$stylesheet" if -f "$css_path/$stylesheet";
   return "css/$stylesheet"       if -f "css/$stylesheet";
   return $stylesheet             if -f $stylesheet;
   return "$css_path/$stylesheet" if -f "$css_path/$stylesheet";
   return "css/$stylesheet"       if -f "css/$stylesheet";
   return $stylesheet             if -f $stylesheet;
+  return $stylesheet             if $stylesheet =~ /^http/; # external
 }
 
 sub get_stylesheet_for_user {
   my $css_path = 'css';
   if (my $user_style = $::myconfig{stylesheet}) {
 }
 
 sub get_stylesheet_for_user {
   my $css_path = 'css';
   if (my $user_style = $::myconfig{stylesheet}) {
-    $user_style =~ s/\.css$//; # nuke trailing .css, this is a remnand of pre 2.7.0 stylesheet handling
+    $user_style =~ s/\.css$//; # nuke trailing .css, this is a remnant of pre 2.7.0 stylesheet handling
     if (-d "$css_path/$user_style" &&
         -f "$css_path/$user_style/main.css") {
       $css_path = "$css_path/$user_style";
     if (-d "$css_path/$user_style" &&
         -f "$css_path/$user_style/main.css") {
       $css_path = "$css_path/$user_style";
@@ -113,11 +153,17 @@ sub get_stylesheet_for_user {
   } else {
     $css_path = "$css_path/kivitendo";
   }
   } else {
     $css_path = "$css_path/kivitendo";
   }
-  $::myconfig{css_path} = $css_path; # needed for menunew, FIXME: don't do this here
 
   return $css_path;
 }
 
 
   return $css_path;
 }
 
+#########################################
+# Javascripts
+########################################
+
+# override in sub layouts
+sub static_javascripts {}
+
 sub add_javascripts {
   &use_javascript
 }
 sub add_javascripts {
   &use_javascript
 }
@@ -125,14 +171,14 @@ sub add_javascripts {
 sub use_javascript {
   my $self = shift;
   push @{ $self->{javascripts} ||= [] }, @_ if @_;
 sub use_javascript {
   my $self = shift;
   push @{ $self->{javascripts} ||= [] }, @_ if @_;
-  @{ $self->{javascripts} ||= [] };
+  map({ $_->use_javascript } $self->sub_layouts), $self->static_javascripts, @{ $self->{javascripts} ||= [] };
 }
 
 sub javascripts {
   my ($self) = @_;
 
   return uniq grep { $_ } map { $self->_find_javascript($_)  }
 }
 
 sub javascripts {
   my ($self) = @_;
 
   return uniq grep { $_ } map { $self->_find_javascript($_)  }
-    map({ $_->javascripts } $self->sub_layouts), $self->use_javascript;
+     $self->use_javascript;
 }
 
 sub _find_javascript {
 }
 
 sub _find_javascript {
@@ -140,6 +186,7 @@ sub _find_javascript {
 
   return "js/$javascript"        if -f "js/$javascript";
   return $javascript             if -f $javascript;
 
   return "js/$javascript"        if -f "js/$javascript";
   return $javascript             if -f $javascript;
+  return $javascript             if $javascript =~ /^http/;
 }
 
 
 }
 
 
@@ -177,7 +224,7 @@ SL::Layout::Base - Base class for layouts
 
 =head1 DESCRIPTION
 
 
 =head1 DESCRIPTION
 
-For a description about the external interface of layouts in general see
+For a description of the external interface of layouts in general see
 L<SL::Layout::Dispatcher>.
 
 This is a base class for layouts in general. It provides the basic interface
 L<SL::Layout::Dispatcher>.
 
 This is a base class for layouts in general. It provides the basic interface
@@ -187,7 +234,7 @@ and some capabilities to extend and cascade layouts.
 =head1 IMPLEMENTING LAYOUT CALLBACKS
 
 There are eight callbacks (C<pre_content>, C<post_content>, C<start_content>,
 =head1 IMPLEMENTING LAYOUT CALLBACKS
 
 There are eight callbacks (C<pre_content>, C<post_content>, C<start_content>,
-C<end_content>, C<stylesheets>, C<stylesheets_inline>, C<javscripts>,
+C<end_content>, C<stylesheets>, C<stylesheets_inline>, C<javascripts>,
 C<javascripts_inline>) which are documented in L<SL::Layout::Dispatcher>. If
 you are writing a new simple layout, you can just override some of them like
 this:
 C<javascripts_inline>) which are documented in L<SL::Layout::Dispatcher>. If
 you are writing a new simple layout, you can just override some of them like
 this:
@@ -252,26 +299,44 @@ For the C<*_content> callbacks this works if you just remember to dispatch to th
     $_[0]->SUPER::post_content
   }
 
     $_[0]->SUPER::post_content
   }
 
-For the stylesheet and javascript callbacks things are hard, because of the
-backwards compatibility, and the built-in sanity checks. The best way currently
-is to just add your content and dispatch to the base method.
 
 
-  sub stylesheets {
-    $_[0]->add_stylesheets(qw(mystyle1.css mystyle2.css);
-    $_[0]->SUPER::stylesheets;
+Stylesheets and Javascripts can be added to every layout and sub-layout at
+runtime with L<SL::Layout::Dispatcher/add_stylesheets> and
+L<SL::Layout::Dispatcher/add_javascripts> (C<use_stylesheets> and
+C<use_javascripts> are aliases for backwards compatibility):
+
+  $layout->add_stylesheets("custom.css");
+  $layout->add_javascripts("app.js", "widget.js");
+
+Or they can be overwritten in sub layouts with the calls
+L<SL::Layout::Displatcher/static_stylesheets> and
+L<SL::Layout::Dispatcher/static_javascripts>:
+
+  sub static_stylesheets {
+    "custom.css"
+  }
+
+  sub static_javascripts {
+    qw(app.css widget.js)
   }
 
   }
 
+Note how these are relative to the base dirs of the currently selected
+stylesheets. Javascripts are resolved relative to the C<js/> basedir.
+
+Setting directly with C<stylesheets> and C<javascripts> is eprecated.
+
+
 =head1 GORY DETAILS ABOUT JAVASCRIPT AND STYLESHEET OVERLOADING
 
 =head1 GORY DETAILS ABOUT JAVASCRIPT AND STYLESHEET OVERLOADING
 
-The original code used to store one stylehsheet in C<< $form->{stylesheet} >> and
+The original code used to store one stylesheet in C<< $form->{stylesheet} >> and
 allowed/expected authors of potential C<bin/mozilla/> controllers to change
 that into their own modified stylesheet.
 
 This was at some point cleaned up into a method C<use stylesheet> which took a
 string of space separated stylesheets and processed them into the response.
 
 allowed/expected authors of potential C<bin/mozilla/> controllers to change
 that into their own modified stylesheet.
 
 This was at some point cleaned up into a method C<use stylesheet> which took a
 string of space separated stylesheets and processed them into the response.
 
-A lot of controllers are still using this methods so the layout interface
-supports it to change as few controller code as possible, while providing the
+A lot of controllers are still using this method so the layout interface
+supports it to change as little controller code as possible, while providing the
 more intuitive C<add_stylesheets> method.
 
 At the same time the following things need to be possible:
 more intuitive C<add_stylesheets> method.
 
 At the same time the following things need to be possible:
@@ -297,7 +362,7 @@ A leaf layout should be able to override a callback to return a list.
 
 Sanitizing
 
 
 Sanitizing
 
-C<stylesheets> needs to retain it's sanitizing behaviour.
+C<stylesheets> needs to retain its sanitizing behaviour.
 
 =item 4.
 
 
 =item 4.
 
@@ -307,7 +372,7 @@ The standard implementation should be able to collect from sub layouts.
 
 =item 5.
 
 
 =item 5.
 
-Preserving of Inclusion Order
+Preserving Inclusion Order
 
 Since there is currently no standard way of mixing own content and including
 sub layouts, this has to be done manually. Certain things like jquery get added
 
 Since there is currently no standard way of mixing own content and including
 sub layouts, this has to be done manually. Certain things like jquery get added
@@ -320,11 +385,15 @@ classes, which should be changed. The other points work pretty well.
 
 =head1 BUGS
 
 
 =head1 BUGS
 
-None yet, if you don't count the horrible stylesheet/javascript interface.
+* stylesheet/javascript interface is a horrible mess.
+
+* It's currently not possible to do compositor layouts without assupmtions
+about the position of the content. That's because the content will return
+control to the actual controller, so the layouts need to know where to split
+pre- and post-content.
 
 =head1 AUTHOR
 
 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
 
 =cut
 
 =head1 AUTHOR
 
 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
 
 =cut
-