From 0f4915834072e2f689ad80709b0801f46d786de9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sven=20Sch=C3=B6ling?= Date: Wed, 18 Sep 2013 14:48:42 +0200 Subject: [PATCH] weitere umstrukturierung --- SL/Controller/DeliveryPlan.pm | 36 +------ SL/Controller/Helper/GetModels.pm | 111 ++++++++++++++------ SL/Controller/Helper/GetModels/Base.pm | 20 +++- SL/Controller/Helper/GetModels/Filtered.pm | 48 +++------ SL/Controller/Helper/GetModels/Paginated.pm | 87 ++++++++------- SL/Controller/Helper/GetModels/Sorted.pm | 26 +++-- 6 files changed, 175 insertions(+), 153 deletions(-) diff --git a/SL/Controller/DeliveryPlan.pm b/SL/Controller/DeliveryPlan.pm index 7d394bebf..f5d5b4e34 100644 --- a/SL/Controller/DeliveryPlan.pm +++ b/SL/Controller/DeliveryPlan.pm @@ -16,32 +16,6 @@ use Rose::Object::MakeMethods::Generic ( __PACKAGE__->run_before(sub { $::auth->assert('sales_order_edit'); }); -#__PACKAGE__->make_filtered( -# MODEL => 'OrderItem', -# LAUNDER_TO => 'filter' -#); -#__PACKAGE__->make_paginated( -# MODEL => 'OrderItem', -# ONLY => [ qw(list) ], -#); -# -#__PACKAGE__->make_sorted( -# MODEL => 'OrderItem', -# ONLY => [ qw(list) ], -# -# DEFAULT_BY => 'reqdate', -# DEFAULT_DIR => 1, -# -# reqdate => t8('Reqdate'), -# description => t8('Description'), -# partnumber => t8('Part Number'), -# qty => t8('Qty'), -# shipped_qty => t8('shipped'), -# not_shipped_qty => t8('not shipped'), -# ordnumber => t8('Order'), -# customer => t8('Customer'), -#); - my %sort_columns = ( reqdate => t8('Reqdate'), description => t8('Description'), @@ -129,10 +103,10 @@ sub action_list { my ($self) = @_; $self->make_filter_summary; + $self->prepare_report; my $orderitems = $self->models->get; - $self->prepare_report; $self->report_generator_list_objects(report => $self->{report}, objects => $orderitems); } @@ -164,6 +138,8 @@ sub prepare_report { $column_defs{$_}->{text} = $sort_columns{$_} for keys %column_defs; + $self->models->disable_plugin('paginated') if $report->{options}{output_format} =~ /^(pdf|csv)$/i; + $self->models->finalize; # for filter laundering $report->set_options( std_column_visibility => 1, controller_class => 'DeliveryPlan', @@ -179,9 +155,7 @@ sub prepare_report { $report->set_column_order(@columns); $report->set_export_options(qw(list filter)); $report->set_options_from_form; - $self->models->sorted->set_report_generator_sort_options(report => $report, sortable_columns => \@sortable); - - $self->models->paginated->disable_pagination if $report->{options}{output_format} =~ /^(pdf|csv)$/i; + $self->models->set_report_generator_sort_options(report => $report, sortable_columns => \@sortable); } sub make_filter_summary { @@ -223,7 +197,7 @@ sub init_models { SL::Controller::Helper::GetModels->new( controller => $self, - model => 'OrderItem', # defaults to controller + model => 'OrderItem', filtered => { launder_to => 'filter', }, diff --git a/SL/Controller/Helper/GetModels.pm b/SL/Controller/Helper/GetModels.pm index ae9810b5c..054bd0b35 100644 --- a/SL/Controller/Helper/GetModels.pm +++ b/SL/Controller/Helper/GetModels.pm @@ -7,46 +7,107 @@ use SL::Controller::Helper::GetModels::Filtered; use SL::Controller::Helper::GetModels::Sorted; use SL::Controller::Helper::GetModels::Paginated; +use Scalar::Util qw(weaken); + use Rose::Object::MakeMethods::Generic ( - scalar => [ qw(controller model query with_objects filtered sorted paginated) ], - 'scalar --get_set_init' => [ qw(handlers) ], + scalar => [ qw(controller model query with_objects filtered sorted paginated finalized final_params) ], + 'scalar --get_set_init' => [ qw(handlers source) ], + array => [ qw(plugins) ], ); use constant PRIV => '__getmodelshelperpriv'; -#my $registered_handlers = {}; + +# official interface + +sub get { + my ($self) = @_; + my %params = $self->finalize; + %params = $self->_run_handlers('get_models', %params); + + return $self->manager->get_all(%params); +} + +sub disable_plugin { + my ($self, $plugin) = @_; + die 'cannot change internal state after finalize was called' if $self->finalized; + die 'unsupported plugin' unless $self->can($plugin) && $self->$plugin && $self->$plugin->isa('SL::Controller::Helper::GetModels::Base'); + $self->$plugin->disabled(1); +} + +sub enable_plugin { + my ($self, $plugin) = @_; + die 'cannot change internal state after finalize was called' if $self->finalized; + die 'unsupported plugin' unless $self->can($plugin) && $self->$plugin && $self->$plugin->isa('SL::Controller::Helper::GetModels::Base'); + $self->$plugin->disabled(0); +} + +sub is_enabled_plugin { + my ($self, $plugin) = @_; + die 'unsupported plugin' unless $self->can($plugin) && $self->$plugin && $self->$plugin->isa('SL::Controller::Helper::GetModels::Base'); + $self->$plugin->is_enabled; +} + +# TODO: get better delegation +sub set_report_generator_sort_options { + my ($self, %params) = @_; + $self->finalize; + + $self->sorted->set_report_generator_sort_options(%params); +} + +sub get_paginate_args { + my ($self) = @_; + my %params = $self->finalize; + + $self->paginated->get_current_paginate_params(%params); +} sub init { my ($self, %params) = @_; -# for my $plugin (qw(filtered sorted paginated)) { -# next unless $params{$plugin}; -# $self->${ \"make_$plugin" }(%{ delete $params{$plugin} || {} }); -# } -# # TODO: default model $self->model(delete $params{model}); + my @plugins; for my $plugin (qw(filtered sorted paginated)) { next unless my $spec = delete $params{$plugin} // {}; my $plugin_class = "SL::Controller::Helper::GetModels::" . ucfirst $plugin; - $self->$plugin($plugin_class->new(%$spec, get_models => $self)); + push @plugins, $self->$plugin($plugin_class->new(%$spec, get_models => $self)); } + $self->plugins(@plugins); $self->SUPER::init(%params); + + $_->read_params for $self->plugins; + + weaken $self->controller if $self->controller; +} + +sub finalize { + my ($self, %params) = @_; + + return %{ $self->final_params } if $self->finalized; + + push @{ $params{query} ||= [] }, @{ $self->query || [] }; + push @{ $params{with_objects} ||= [] }, @{ $self->with_objects || [] }; + + %params = $_->finalize(%params) for $self->plugins; + + $self->finalized(1); + $self->final_params(\%params); + + return %params; } sub register_handlers { my ($self, %additional_handlers) = @_; -# my $only = delete($additional_handlers{ONLY}) || []; -# $only = [ $only ] if !ref $only; -# my %hook_params = @{ $only } ? ( only => $only ) : (); - my $handlers = $self->handlers; map { push @{ $handlers->{$_} }, $additional_handlers{$_} if $additional_handlers{$_} } keys %$handlers; } +# TODO fix this sub get_models_url_params { my ($class, $sub_name_or_code) = @_; @@ -71,26 +132,6 @@ sub get_callback { return $self->controller->url_for(%default_params, %override_params); } -sub get { - my ($self, %params) = @_; - - push @{ $params{query} ||= [] }, @{ $self->query || [] }; - push @{ $params{with_objects} ||= [] }, @{ $self->with_objects || [] }; - - %params = $self->_run_handlers('get_models', %params); - - return $self->manager->get_all(%params); -} - -sub get_paginate_args { - my ($self, %params) = @_; - - push @{ $params{query} ||= [] }, @{ $self->query || [] }; - push @{ $params{with_objects} ||= [] }, @{ $self->with_objects || [] }; - - $self->paginated->get_current_paginate_params(%params); -} - sub manager { die "No 'model' to work on" unless $_[0]->model; "SL::DB::Manager::" . $_[0]->model; @@ -123,6 +164,10 @@ sub init_handlers { } } +sub init_source { + $::form +} + 1; __END__ diff --git a/SL/Controller/Helper/GetModels/Base.pm b/SL/Controller/Helper/GetModels/Base.pm index 3d28de5d1..97aa84d0c 100644 --- a/SL/Controller/Helper/GetModels/Base.pm +++ b/SL/Controller/Helper/GetModels/Base.pm @@ -4,11 +4,15 @@ use strict; use parent 'Rose::Object'; use Scalar::Util qw(weaken); - use Rose::Object::MakeMethods::Generic ( - scalar => [ qw(get_models) ], + scalar => [ qw(get_models disabled finalized) ], ); +# phase stubs +sub read_params { die 'implement me' } + +sub finalize { die 'implement me' } + sub set_get_models { $_[0]->get_models($_[1]); @@ -23,7 +27,19 @@ sub merge_args { $final_args->{$field} = [ map { @{ $_->{$field} || [] } } @args ]; } + for my $field (qw(page per_page sort_by sort_dir )) { + for my $arg (@args) { + next unless defined $_->{$field}; + $final_args->{$field} //= $_->{$field}; + } + } + return %$final_args; } +sub is_enabled { + my ($self) = @_; + return !$self->disabled; +} + 1; diff --git a/SL/Controller/Helper/GetModels/Filtered.pm b/SL/Controller/Helper/GetModels/Filtered.pm index 3374471cc..c89d44d6b 100644 --- a/SL/Controller/Helper/GetModels/Filtered.pm +++ b/SL/Controller/Helper/GetModels/Filtered.pm @@ -8,7 +8,7 @@ use SL::Controller::Helper::ParseFilter (); use List::MoreUtils qw(uniq); use Rose::Object::MakeMethods::Generic ( - scalar => [ qw(disabled filter_args filter_params) ], + scalar => [ qw(filter_args filter_params orig_filter) ], 'scalar --get_set_init' => [ qw(form_params launder_to) ], ); @@ -26,20 +26,15 @@ sub init { # $::lxdebug->dump(0, "CONSPEC", \%specs); } -sub get_current_filter_params { - my ($self) = @_; +sub read_params { + my ($self, %params) = @_; - return $self->filter_params if $self->filter_params; + return %{ $self->filter_params } if $self->filter_params; + my $source = $self->get_models->source; - require Carp; - Carp::confess('It seems a GetModels plugin tries to access filter params before they got calculated. Make sure your make_filtered call comes first.'); -} + my $filter = $params{filter} // $source->{ $self->form_params } // {}; + $self->orig_filter($filter); -sub _make_current_filter_params { - my ($self, %params) = @_; - -# my $spec = $self->get_filter_spec; - my $filter = $params{filter} // $::form->{ $self->form_params } // {}, my %filter_args = $self->_get_filter_args; my %parse_filter_args = ( class => $self->get_models->manager, @@ -58,19 +53,6 @@ sub _make_current_filter_params { my %calculated_params = SL::Controller::Helper::ParseFilter::parse_filter($filter, %parse_filter_args); %calculated_params = $self->merge_args(\%calculated_params, \%filter_args, \%params); -# $calculated_params{query} = [ -# @{ $calculated_params{query} || [] }, -# @{ $filter_args{ query} || [] }, -# @{ $params{ query} || [] }, -# ]; -# -# $calculated_params{with_objects} = [ -# uniq -# @{ $calculated_params{with_objects} || [] }, -# @{ $filter_args{ with_objects} || [] }, -# @{ $params{ with_objects} || [] }, -# ]; - if ($laundered) { if ($self->get_models->controller->can($self->launder_to)) { $self->get_models->controller->${\ $self->launder_to }($laundered); @@ -86,9 +68,9 @@ sub _make_current_filter_params { return %calculated_params; } -sub disable_filtering { - my ($self) = @_; - $self->disabled(1); +sub finalize { + my ($self, %params) = @_; + %params; } # @@ -107,7 +89,7 @@ sub _callback_handler_for_filtered { my ($self, %params) = @_; if ($self->is_enabled) { - my ($flattened) = SL::Controller::Helper::ParseFilter::flatten($::form->{ $self->form_params }, $self->form_params); + my ($flattened) = SL::Controller::Helper::ParseFilter::flatten($self->orig_filter, $self->form_params); %params = (%params, @{ $flattened || [] }); } @@ -122,15 +104,11 @@ sub _get_models_handler_for_filtered { # $::lxdebug->dump(0, "params in get_models_for_filtered", \%params); my %filter_params; - %filter_params = $self->_make_current_filter_params(%params) if $self->is_enabled; + %filter_params = $self->read_params(%params) if $self->is_enabled; # $::lxdebug->dump(0, "GM handler for filtered; params nach modif (is_enabled? " . $self->is_enabled . ")", \%params); - return (%params, %filter_params); -} - -sub is_enabled { - !$_[0]->disabled; + return $self->merge_args(\%params, \%filter_params); } sub init_form_params { diff --git a/SL/Controller/Helper/GetModels/Paginated.pm b/SL/Controller/Helper/GetModels/Paginated.pm index a40acaef9..fc61ac573 100644 --- a/SL/Controller/Helper/GetModels/Paginated.pm +++ b/SL/Controller/Helper/GetModels/Paginated.pm @@ -6,7 +6,7 @@ use parent 'SL::Controller::Helper::GetModels::Base'; use List::Util qw(min); use Rose::Object::MakeMethods::Generic ( - scalar => [ qw(disabled per_page) ], + scalar => [ qw(per_page form_data paginated_args calculated_params) ], 'scalar --get_set_init' => [ qw(form_params paginate_args) ], ); @@ -26,17 +26,39 @@ sub init { # $::lxdebug->dump(0, "CONSPEC", \%specs); } -sub get_current_paginate_params { - my ($self, %args) = @_; - return () unless $self->is_enabled; +sub read_params { + my ($self, %params) = @_; + + return %{ $self->form_data } if $self->form_data; + my $source = $self->get_models->source; + + my $from_form = { + page => $source->{ $self->form_params->[0] } || 1, + per_page => $source->{ $self->form_params->[1] } * 1, + }; - my %paginate_params = $self->final_params(%args); +# my $priv = _priv($self); + $params{page} = $from_form->{page} unless defined $params{page}; + $params{per_page} = $from_form->{per_page} unless defined $params{per_page}; + + $params{page} = ($params{page} * 1) || 1; + $params{per_page} = ($params{per_page} * 1) || $self->per_page; + + $self->form_data(\%params); + + %params; +} + +sub finalize { + my ($self, %args) = @_; +# return () unless $self->is_enabled; + my %paginate_params = $self->read_params; # try to use Filtered if available and nothing else is configured, but don't # blow up if the controller does not use Filtered my %paginate_args = ref($self->paginate_args) eq 'CODE' ? %{ $self->paginate_args->($self) } : $self->paginate_args eq '__FILTER__' - && $self->get_models->filtered ? %{ $self->get_models->filtered->get_current_filter_params } + && $self->get_models->filtered ? $self->get_models->filtered->read_params : $self->paginate_args ne '__FILTER__' ? do { my $sub = $self->paginate_args; %{ $self->get_models->controller->$sub() } } : (); @@ -44,50 +66,25 @@ sub get_current_paginate_params { my $calculated_params = $self->get_models->manager->paginate(%paginate_params, args => \%args); - # $::lxdebug->dump(0, "get_current_paginate_params: ", $calculated_params); + $self->paginated_args(\%args); + $self->calculated_params($calculated_params); - return %{ $calculated_params }; + return %args; } -sub disable_pagination { - my ($self) = @_; - $self->disabled(1); -} - -sub final_params { - my ($self, %params) = @_; - - my $from_form = { - page => $::form->{ $self->form_params->[0] } || 1, - per_page => $::form->{ $self->form_params->[1] } * 1, - }; - -# my $priv = _priv($self); - $params{page} = $from_form->{page} unless defined $params{page}; - $params{per_page} = $from_form->{per_page} unless defined $params{per_page}; - - $params{page} = ($params{page} * 1) || 1; - $params{per_page} = ($params{per_page} * 1) || $self->per_page; - - %params; +sub get_current_paginate_params { + my ($self, %args) = @_; + return () unless $self->is_enabled; + %{ $self->calculated_params }; } # # private functions # -sub init_form_params { - [ qw(page per_page) ] -} - -sub init_paginate_args { - '__FILTER__' -} - sub _callback_handler_for_paginated { my ($self, %params) = @_; - my %form_params = $self->final_params; -# my $priv = _priv($self); + my %form_params = $self->read_params; if ($self->is_enabled && $form_params{page}) { $params{ $self->form_params->[0] } = $form_params{page}; @@ -102,16 +99,18 @@ sub _callback_handler_for_paginated { sub _get_models_handler_for_paginated { my ($self, %params) = @_; - $self->get_models->manager->paginate($self->final_params, args => \%params) if $self->is_enabled; + $self->get_models->manager->paginate(%{ $self->calculated_params }, args => \%params) if $self->is_enabled; # $::lxdebug->dump(0, "GM handler for paginated; params nach modif (is_enabled? " . _is_enabled($self) . ")", \%params); - return %params; } -sub is_enabled { - my ($self) = @_; - return !$self->disabled; +sub init_form_params { + [ qw(page per_page) ] +} + +sub init_paginate_args { + '__FILTER__' } 1; diff --git a/SL/Controller/Helper/GetModels/Sorted.pm b/SL/Controller/Helper/GetModels/Sorted.pm index 9e133b8f6..c154d753c 100644 --- a/SL/Controller/Helper/GetModels/Sorted.pm +++ b/SL/Controller/Helper/GetModels/Sorted.pm @@ -7,7 +7,7 @@ use Carp; use List::MoreUtils qw(uniq); use Rose::Object::MakeMethods::Generic ( - scalar => [ qw(by dir specs) ], + scalar => [ qw(by dir specs form_data) ], 'scalar --get_set_init' => [ qw(form_params) ], ); @@ -43,16 +43,19 @@ sub init { # $::lxdebug->dump(0, "CONSPEC", \%specs); } -sub get_current_sort_params { +sub read_params { my ($self, %params) = @_; + return %{ $self->form_data } if $self->form_data; + my %sort_params; my ($by, $dir) = @{ $self->form_params }; + my $source = $self->get_models->source; - if ($::form->{ $by }) { + if ($source->{ $by }) { %sort_params = ( - sort_by => $::form->{$by}, - sort_dir => defined($::form->{$dir}) ? $::form->{$dir} * 1 : undef, + sort_by => $source->{$by}, + sort_dir => defined($source->{$dir}) ? $source->{$dir} * 1 : undef, ); } elsif (!$self->by) { %sort_params = %params; @@ -63,15 +66,22 @@ sub get_current_sort_params { ); } + $self->form_data(\%sort_params); + return %sort_params; } +sub finalize { + my ($self, %params) = @_; + %params; +} + sub set_report_generator_sort_options { my ($self, %params) = @_; $params{$_} or croak("Missing parameter '$_'") for qw(report sortable_columns); - my %current_sort_params = $self->get_current_sort_params; + my %current_sort_params = $self->read_params; foreach my $col (@{ $params{sortable_columns} }) { $params{report}->{columns}->{$col}->{link} = $self->get_models->get_callback( @@ -96,7 +106,7 @@ sub set_report_generator_sort_options { sub _callback_handler_for_sorted { my ($self, %params) = @_; - my %spec = $self->get_current_sort_params; + my %spec = $self->read_params; if ($spec{sort_by}) { $params{ $self->form_params->[0] } = $spec{sort_by}; @@ -111,7 +121,7 @@ sub _callback_handler_for_sorted { sub _get_models_handler_for_sorted { my ($self, %params) = @_; - my %sort_params = $self->get_current_sort_params; + my %sort_params = $self->read_params; my $sort_spec = $self->specs->{ $sort_params{sort_by} }; $params{sort_by} = "SL::DB::Manager::$sort_spec->{model}"->make_sort_string(sort_by => $sort_spec->{model_column}, sort_dir => $sort_params{sort_dir}); -- 2.20.1