From: Niclas Zimmermann Date: Fri, 15 Mar 2013 09:29:40 +0000 (+0100) Subject: Merge branch 'master' of github.com:kivitendo/kivitendo-erp X-Git-Tag: release-3.1.0beta1~509^2 X-Git-Url: http://wagnertech.de/gitweb/gitweb.cgi/mfinanz.git/commitdiff_plain/cd73950c9f7616255cf917e36a6e1a03627f860d?hp=94ee5a7f5deddb1bf33855681c7a88dacaae2a11 Merge branch 'master' of github.com:kivitendo/kivitendo-erp --- diff --git a/SL/Git.pm b/SL/Git.pm index a292a78ef..76fd8e6c6 100644 --- a/SL/Git.pm +++ b/SL/Git.pm @@ -34,6 +34,7 @@ sub get_log { my $in = IO::File->new($self->git_exe . qq! log --format='tformat:\%H|\%an|\%ae|\%ai|\%s' ${since_until} |!); if (!$in) { + no warnings 'once'; $::lxdebug->message(LXDebug::WARN(), "Error spawning git: $!"); return (); } diff --git a/SL/Layout/Base.pm b/SL/Layout/Base.pm index bd08d8164..2212f718e 100644 --- a/SL/Layout/Base.pm +++ b/SL/Layout/Base.pm @@ -1,7 +1,7 @@ package SL::Layout::Base; use strict; -use parent qw(SL::Controller::Base); +use parent qw(Rose::Object); use List::MoreUtils qw(uniq); use Time::HiRes qw(); @@ -18,6 +18,7 @@ use Rose::Object::MakeMethods::Generic ( ); use SL::Menu; +use SL::Presenter; my %menu_cache; @@ -154,4 +155,176 @@ sub need_footer { $_[0]{_header_done}; } +sub presenter { + SL::Presenter->get; +} + 1; + +__END__ + +=encoding utf-8 + +=head1 NAME + +SL::Layout::Base - Base class for layouts + +=head1 SYNOPSIS + + package SL::Layout::MyLayout; + + use parent qw(SL::Layout::Base); + +=head1 DESCRIPTION + +For a description about the external interface of layouts in general see +L. + +This is a base class for layouts in general. It provides the basic interface +and some capabilities to extend and cascade layouts. + + +=head1 IMPLEMENTING LAYOUT CALLBACKS + +There are eight callbacks (C, C, C, +C, C, C, C, +C) which are documented in L. If +you are writing a new simple layout, you can just override some of them like +this: + + package SL::Layout::MyEvilLayout; + + sub pre_content { + '

This is MY page now

' + } + + sub post_content { + '

Brought to you by my own layout class

' + } + + +To preserve the sanitizing effects of C and C you should instead do the following: + + sub stylesheets { + $_[0]->add_stylesheets(qw(mystyle1.css mystyle2.css); + $_[0]->SUPER::stylesheets; + } + +If you want to add something to a different layout, you should write a sub +layout and add it to the other layouts. + + +=head1 SUB LAYOUTS + +Layouts can be aggregated, so that common elements can be used in different +layouts. Currently this is used for the L sub layout, +which contains a lot of the stylesheets and javascripts necessary. Another +example is the L layout, which is used to generate a +common top bar for all menu types. + +To add a sub layout to your layout just overwrite the sub_layout method: + + package SL::Layout::MyFinalLayout; + + sub init_sub_layout { + [ + SL::Layout::None->new, + SL::Layout::MyEvilLayout->new, + ] + } + +You can also add a sublayout at runtime: + + $layout->add_sub_layout(SL::Layout::SideBar->new); + +The standard implementation for the callbacks will see to it that the contents +of all sub layouts will get rendered. + + +=head1 COMBINING SUB LAYOUTS AND OWN BEHAVIOUR + +This is still somewhat rough, and improvements are welcome. + +For the C<*_content> callbacks this works if you just remember to dispatch to the base method: + + sub post_content { + return $_[0]->render_status_bar . + $_[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; + } + +=head1 GORY DETAILS ABOUT JAVASCRIPT AND STYLESHEET OVERLOADING + +The original code used to store one stylehsheet in C<< $form->{stylesheet} >> and +allowed/expected authors of potential C controllers to change +that into their own modified stylesheet. + +This was at some point cleaned up into a method C 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 +more intuitive C method. + +At the same time the following things need to be possible: + +=over 4 + +=item 1. + +Runtime additions. + + $layout->add_stylesheets(...) + +Since add_stylesheets adds to C<< $self->{stylesheets} >> there must be a way to read +from it. Currently this is the deprecated C. + +=item 2. + +Overriding Callbacks + +A leaf layout should be able to override a callback to return a list. + +=item 3. + +Sanitizing + +C needs to retain it's sanitizing behaviour. + +=item 4. + +Aggregation + +The standard implementation should be able to collect from sub layouts. + +=item 5. + +Preserving of 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 +in L so that they get rendered first. + +=back + +The current implementation provides no good candidate for overriding in sub +classes, which should be changed. The other points work pretty well. + +=head1 BUGS + +None yet, if you don't count the horrible stylesheet/javascript interface. + +=head1 AUTHOR + +Sven Schöling Es.schoeling@linet-services.deE + +=cut + diff --git a/SL/Layout/Dispatcher.pm b/SL/Layout/Dispatcher.pm index 5d7688e2c..3dcde2733 100644 --- a/SL/Layout/Dispatcher.pm +++ b/SL/Layout/Dispatcher.pm @@ -20,3 +20,188 @@ sub new { } 1; + +__END__ + +=encoding utf-8 + +=head1 NAME + +SL::Layout::Dispatcher - provides layouts by name. + +=head1 SYNOPSIS + + use SL::Layout::Dispatcher; + $::request->layout(SL::Layout::Dispatcher->new(style => 'login')); + + # same as + + use SL::Layout::Login; + $::request->layout(SL::Layout::Login->new); + +=head1 INTRODUCTION + +A layout in kivitendo is anything that should be included into a text/html +response without having each controller do it manually. This includes: + +=over 4 + +=item * + +menus + +=item * + +status bars + +=item + +div containers for error handling and ajax responses + +=item * + +javascript and css includes + +=item * + +html header and body + +=back + +It does not include: + +=over 4 + +=item * + +http headers + +=item * + +anthing that is not a text/html response + +=back + +All of these tasks are handled by a layout object, which is stored in the +global L<$::request|SL::Request> object. An appropriate layout object will be +chosen during the login/session_restore process. + + +=head1 INTERFACE + +Every layout must be instantiated from L and must implement +the following eight callbacks: + +=over 4 + +=item C + +Content that must, for whatever reason, appear before the main content. + +=item C + +An introcutory clause for the main content. Usually something like C<<
>>. + +=item C + +The corresponding end of L like C<<
>> + +=item C + +Any extra content that should appear after the main content in the response +source. Note that it is preferred to put extra content after the main content, +so that it gets rendered faster. + +=item C + +A list of stylesheets that should be included as a full relative web path. Will +be rendered into the html header. + +=item C + +A list of stylesheet snippets that need to be included in the response. Will be +added to the html header. + +=item C + +A list of javascripts that should be included as a full relative web path. + +Note: +There is no guarantee where these will end up in the content. Currently they +will be rendered into the header, but are likely to be moved into the footer in +the future. + +=item C + +A list of javascript snippets that need to be included in the response. + +Note: +These will end up in the footer, so make sure they don't contain +initializations to static javascript includes that may be included earlier. + +=back + +=head1 RUNTIME INTERFACE + +Each layout object can add stylesheets and javascripts at runtime, as long as +its before the actual rendering has begun. This can be used to add special +javascripts only your controller needs. + +=over 4 + +=item C + +Adds the list of arguments to the list of used stylesheets. + +These will first be searched in the theme folder for the current user, and only +after that be searched from the common C folder. + +Duplicated files will be only included once. + +Non-existing files will be pruned from the list. + +=item C + +Backwards compatible alias for C. Deprecated. + +=item C + +Adds the list of arguments to the list of used javascripts. + +Duplicated files will be only included once. + +Non-existing files will be pruned from the list. + +=item C + +Backwards compatible alias for C. Deprecated. + +=item C + +Add a snippet of javascript. + +=item C + +Add a snippet of css. + +=item C + +If set with a selector, the layout will generate javascript to set the page +focus to that selector on document.ready. + +=back + +=head1 BUGS + +None yet :) + +=head1 TODO + +non existing css or js includes should generate a log entry. + +=head1 AUTHOR + +Sven Schöling Es.schoeling@linet-services.deE + +=cut diff --git a/SL/Layout/Javascript.pm b/SL/Layout/Javascript.pm index 2cda0f459..b08cf6dcc 100644 --- a/SL/Layout/Javascript.pm +++ b/SL/Layout/Javascript.pm @@ -47,7 +47,7 @@ sub display { $callback = URI->new($callback)->rel($callback) if $callback; $callback = "login.pl?action=company_logo" if $callback =~ /^(\.\/)?$/; - $self->render("menu/menunew", { output => 0 }, + $self->presenter->render("menu/menunew", force_ul_width => 1, date => $self->clock_line, menu_items => $self->acc_menu, diff --git a/SL/Layout/MenuLeft.pm b/SL/Layout/MenuLeft.pm index d740640c6..9a47d292d 100644 --- a/SL/Layout/MenuLeft.pm +++ b/SL/Layout/MenuLeft.pm @@ -15,7 +15,7 @@ sub javascripts_inline { my $self = shift; $self->SUPER::javascripts_inline; my $sections = [ section_menu($self->menu) ]; - $self->render('menu/menu', { output => 0 }, + $self->presenter->render('menu/menu', sections => $sections, ) } diff --git a/SL/Layout/None.pm b/SL/Layout/None.pm index 971ef857a..4a02d652a 100644 --- a/SL/Layout/None.pm +++ b/SL/Layout/None.pm @@ -14,9 +14,9 @@ sub javascripts_inline { s/y+/yy/gi; } $::myconfig{dateformat}; - return $self->render( + return $self->presenter->render( 'layout/javascript_setup', - { type => 'js', output => 0, }, + { type => 'js' }, datefmt => $datefmt, focus => $::request->layout->focus, ajax_spinner => 1, diff --git a/SL/Layout/Top.pm b/SL/Layout/Top.pm index 9c4fdea36..a838aeee1 100644 --- a/SL/Layout/Top.pm +++ b/SL/Layout/Top.pm @@ -6,7 +6,7 @@ use parent qw(SL::Layout::Base); sub pre_content { my ($self) = @_; - $self->SUPER::render('menu/header', { output => 0 }, + $self->presenter->render('menu/header', now => DateTime->now_local, is_fastcgi => scalar($::dispatcher->interface_type =~ /fastcgi/i), is_links => scalar($ENV{HTTP_USER_AGENT} =~ /links/i)); diff --git a/SL/Layout/V3.pm b/SL/Layout/V3.pm index 9d5e37d86..03c6f3ebf 100644 --- a/SL/Layout/V3.pm +++ b/SL/Layout/V3.pm @@ -164,7 +164,7 @@ sub render { $callback = URI->new($callback)->rel($callback) if $callback; $callback = "login.pl?action=company_logo" if $callback =~ /^(\.\/)?$/; - $self->SUPER::render('menu/menuv3', { output => 0 }, + $self->presenter->render('menu/menuv3', force_ul_width => 1, date => $self->clock_line, menu => $self->print_menu, diff --git a/SL/Request.pm b/SL/Request.pm index 5a840a641..4479bd73a 100644 --- a/SL/Request.pm +++ b/SL/Request.pm @@ -522,6 +522,13 @@ an 'AJAX' request. Returns the requested content type (either C, C or C). +=item C + +Set and retrieve the layout object for the current request. Must be an instance +of L. Defaults to an isntance of L. + +For more information about layouts, see L. + =back =head1 SPECIAL FUNCTIONS diff --git a/t/007broken_links.t b/t/007broken_links.t index 93148f4d4..fbe5ea21b 100644 --- a/t/007broken_links.t +++ b/t/007broken_links.t @@ -37,8 +37,8 @@ find(sub { $finder->find(\$text); - }, "." -); + }, "./templates", "./doc", + ); if (@fails) { ok(0, join "\n", @fails); diff --git a/t/controllers/base/render.t b/t/controllers/base/render.t index 0f252bbe2..0a15078e0 100644 --- a/t/controllers/base/render.t +++ b/t/controllers/base/render.t @@ -7,6 +7,8 @@ use lib 't'; use Support::TestSetup; use SL::Presenter; +use SL::Controller::Base; +use SL::Layout::Javascript; no warnings 'uninitialized';