X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FHelper%2FCsv%2FDispatcher.pm;h=add444b9d751d670410cacf302979f5177acf89d;hb=7ff0d2ab41abd45fa1d45e6401a3f33c1ebddecd;hp=3b6044342385da57d4c38e38af57a2e07fbd1dd5;hpb=417cc3a7e5d4a96713b71b1d723196bddeeb01cc;p=kivitendo-erp.git diff --git a/SL/Helper/Csv/Dispatcher.pm b/SL/Helper/Csv/Dispatcher.pm index 3b6044342..add444b9d 100644 --- a/SL/Helper/Csv/Dispatcher.pm +++ b/SL/Helper/Csv/Dispatcher.pm @@ -9,6 +9,8 @@ use Rose::Object::MakeMethods::Generic scalar => [ qw( _specs _errors ) ]; +use SL::Helper::Csv::Error; + sub new { my ($class, $parent) = @_; my $self = bless { }, $class; @@ -32,11 +34,23 @@ sub apply { return unless $value; for my $step (@{ $spec->{steps} }) { - my ($acc, $class) = @$step; + my ($acc, $class, $index) = @$step; if ($class) { - eval "require $class; 1" or die "could not load class '$class'"; - $obj->$acc($class->new) if ! $obj->$acc; - $obj = $obj->$acc; + + # autovifify + if (defined $index) { + if (! $obj->$acc || !$obj->$acc->[$index]) { + my @objects = $obj->$acc; + $obj->$acc(@objects, map { $class->new } 0 .. $index - @objects); + } + $obj = $obj->$acc->[$index]; + } else { + if (! $obj->$acc) { + $obj->$acc($class->new); + } + $obj = $obj->$acc; + } + } else { $obj->$acc($value); } @@ -57,7 +71,19 @@ sub parse_profile { for my $col (@$header) { next unless $col; - push @specs, $self->make_spec($col, $profile->{$col} || $col); + if ($self->_csv->strict_profile) { + if (exists $profile->{$col}) { + push @specs, $self->make_spec($col, $profile->{$col}); + } else { + $self->unknown_column($col, undef); + } + } else { + if (exists $profile->{$col}) { + push @specs, $self->make_spec($col, $profile->{$col}); + } else { + push @specs, $self->make_spec($col, $col); + } + } } $self->_specs(\@specs); @@ -69,14 +95,32 @@ sub make_spec { my ($self, $col, $path) = @_; my $spec = { key => $col, steps => [] }; + + return unless $path; + my $cur_class = $self->_csv->class; - for my $step ( split /\./, $path ) { + return unless $cur_class; + + for my $step_index ( split /\.(?!\d)/, $path ) { + my ($step, $index) = split /\./, $step_index; if ($cur_class->can($step)) { - if ($cur_class->meta->relationship($step)) { #a - my $next_class = $cur_class->meta->relationship($step)->class; - push @{ $spec->{steps} }, [ $step, $next_class ]; - $cur_class = $next_class; + if (my $rel = $cur_class->meta->relationship($step)) { #a + if ($index && ! $rel->isa('Rose::DB::Object::Metadata::Relationship::OneToMany')) { + $self->_push_error([ + $path, + undef, + "Profile path error. Indexed relationship is not OneToMany around here: '$step_index'", + undef, + 0, + ]); + return; + } else { + my $next_class = $cur_class->meta->relationship($step)->class; + push @{ $spec->{steps} }, [ $step, $next_class, $index ]; + $cur_class = $next_class; + eval "require $cur_class; 1" or die "could not load class '$cur_class'"; + } } else { # simple dispatch push @{ $spec->{steps} }, [ $step ]; last; @@ -112,7 +156,7 @@ sub errors { sub _push_error { my ($self, @errors) = @_; - my @new_errors = ($self->errors, @errors); + my @new_errors = ($self->errors, map { SL::Helper::Csv::Error->new(@$_) } @errors); $self->_errors(\@new_errors); }