Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision c8473408

Von Bernd Blessmann vor etwa 11 Jahren hinzugefügt

  • ID c8473408202bb3b821a14cee9f8945405d8eeffc
  • Vorgänger f33995ff
  • Nachfolger af205393

SL::Helper::Csv bekommt Klasse im Profil mitgeteilt.

Unterschiede anzeigen:

SL/Controller/CsvImport/Base.pm
31 31
  my $profile = $self->profile;
32 32
  $self->csv(SL::Helper::Csv->new(file                   => $self->file->file_name,
33 33
                                  encoding               => $self->controller->profile->get('charset'),
34
                                  class                  => $self->class,
35
                                  profile                => $profile,
34
                                  profile                => { profile => $profile, class => $self->class },
36 35
                                  ignore_unknown_columns => 1,
37 36
                                  strict_profile         => 1,
38 37
                                  case_insensitive_header => 1,
SL/Helper/Csv.pm
9 9
use Params::Validate qw(:all);
10 10
use Text::CSV_XS;
11 11
use Rose::Object::MakeMethods::Generic scalar => [ qw(
12
  file encoding sep_char quote_char escape_char header profile class
12
  file encoding sep_char quote_char escape_char header profile
13 13
  numberformat dateformat ignore_unknown_columns strict_profile _io _csv
14 14
  _objects _parsed _data _errors all_cvar_configs case_insensitive_header
15 15
) ];
......
29 29
    profile                => { type    => HASHREF,  optional => 1 },
30 30
    file                   => 1,
31 31
    encoding               => 0,
32
    class                  => 0,
33 32
    numberformat           => 0,
34 33
    dateformat             => 0,
35 34
    ignore_unknown_columns => 0,
......
71 70

  
72 71
sub get_objects {
73 72
  my ($self, %params) = @_;
74
  croak 'no class given'   unless $self->class;
75 73
  croak 'must parse first' unless $self->_parsed;
76 74

  
77 75
  $self->_make_objects unless $self->_objects;
......
188 186
  my ($self, %params) = @_;
189 187
  my @objs;
190 188

  
191
  eval "require " . $self->class;
192 189
  local $::myconfig{numberformat} = $self->numberformat if $self->numberformat;
193 190
  local $::myconfig{dateformat}   = $self->dateformat   if $self->dateformat;
194 191

  
195 192
  for my $line (@{ $self->_data }) {
196
    my $tmp_obj = $self->class->new;
197
    $self->dispatcher->dispatch($tmp_obj, $line);
193
    my $tmp_obj = $self->dispatcher->dispatch($line);
198 194
    push @objs, $tmp_obj;
199 195
  }
200 196

  
......
248 244
    quote_char  => '\'',    # default '"'
249 245
    escape_char => '"',     # default '"'
250 246
    header      => [qw(id text sellprice word)], # see later
251
    profile     => { sellprice => 'sellprice_as_number' },
252
    class       => 'SL::DB::CsvLine',   # if present, map lines to this
247
    profile     => { profile => { sellprice => 'sellprice_as_number'}, class => SL::DB::Part },
253 248
  );
254 249

  
255 250
  my $status  = $csv->parse;
......
348 343
Can be an array of columns, in this case the first line is not used as a
349 344
header. Empty header fields will be ignored in objects.
350 345

  
351
=item C<profile> \%ACCESSORS
346
=item C<profile> {profile => \%ACCESSORS, class => class}
352 347

  
353
May be used to map header fields to custom accessors. Example:
348
This is a HASHREF to hash which may contain the keys C<profile> and C<class>.
354 349

  
355
  { listprice => listprice_as_number }
350
The C<profile> is a HASHREF which may be used to map header fields to custom
351
accessors. Example:
352

  
353
  {profile => { listprice => listprice_as_number }}
356 354

  
357 355
In this case C<listprice_as_number> will be used to read in values from the
358 356
C<listprice> column.
......
360 358
In case of a One-To-One relationsship these can also be set over
361 359
relationsships by sparating the steps with a dot (C<.>). This will work:
362 360

  
363
  { customer => 'customer.name' }
361
  {profile => { customer => 'customer.name' }}
364 362

  
365 363
And will result in something like this:
366 364

  
......
373 371
will have to do that for yourself. Since you provided the profile, it is
374 372
assumed you know what to do in this case.
375 373

  
376
If no profile is given, any header field found will be taken as is.
377

  
378
If the path in a profile entry is empty, the field will be subjected to
379
C<strict_profile> and C<case_insensitive_header> checking, will be parsed into
380
C<get_data>, but will not be attempted to be dispatched into objects.
381

  
382
=item C<class>
383

  
384
If present, the line will be handed to the new sub of this class,
374
If C<class> is present, the line will be handed to the new sub of this class,
385 375
and the return value used instead of the line itself.
386 376

  
387 377
=item C<ignore_unknown_columns>
......
442 432
Dispatch to child objects, like this:
443 433

  
444 434
 $csv = SL::Helper::Csv->new(
445
   file  => ...
446
   class => SL::DB::Part,
447
   profile => [
448
     makemodel => {
449
       make_1  => make,
450
       model_1 => model,
451
     },
452
     makemodel => {
453
       make_2  => make,
454
       model_2 => model,
455
     },
456
   ]
435
   file    => ...
436
   profile => {
437
     profile => [
438
       makemodel => {
439
         make_1  => make,
440
         model_1 => model,
441
       },
442
       makemodel => {
443
         make_2  => make,
444
         model_2 => model,
445
       },
446
     ],
447
     class   => SL::DB::Part,
448
   }
457 449
 );
458 450

  
459 451
=head1 AUTHOR
SL/Helper/Csv/Dispatcher.pm
22 22
}
23 23

  
24 24
sub dispatch {
25
  my ($self, $obj, $line) = @_;
25
  my ($self, $line) = @_;
26

  
27
  eval "require " . $self->_csv->profile->{class};
28
  my $obj = $self->_csv->profile->{class}->new;
26 29

  
27 30
  for my $spec (@{ $self->_specs }) {
28 31
    $self->apply($obj, $spec, $line->{$spec->{key}});
29 32
  }
33

  
34
  return $obj;
30 35
}
31 36

  
32 37
sub apply {
......
66 71
  my ($self, %params) = @_;
67 72

  
68 73
  my $header  = $self->_csv->header;
69
  my $profile = $self->_csv->profile;
74
  my $profile = $self->_csv->profile->{profile};
70 75
  my @specs;
71 76

  
72 77
  for my $col (@$header) {
......
98 103

  
99 104
  return unless $path;
100 105

  
101
  my $cur_class = $self->_csv->class;
106
  my $cur_class = $self->_csv->profile->{class};
102 107

  
103 108
  return unless $cur_class;
104 109

  
t/helper/csv.t
11 11
Support::TestSetup::login();
12 12

  
13 13
my $csv = SL::Helper::Csv->new(
14
  file   => \"Kaffee\n",
15
  header => [ 'description' ],
16
  class  => 'SL::DB::Part',
14
  file    => \"Kaffee\n",
15
  header  => [ 'description' ],
16
  profile => { class  => 'SL::DB::Part', },
17 17
);
18 18

  
19 19
isa_ok $csv->_csv, 'Text::CSV_XS';
......
28 28
$::myconfig{dateformat} = 'dd.mm.yyyy';
29 29

  
30 30
$csv = SL::Helper::Csv->new(
31
  file   => \"Kaffee;0.12;12,2;1,5234\n",
32
  header => [ 'description', 'sellprice', 'lastcost_as_number', 'listprice' ],
33
  profile => { listprice => 'listprice_as_number' },
34
  class  => 'SL::DB::Part',
31
  file    => \"Kaffee;0.12;12,2;1,5234\n",
32
  header  => [ 'description', 'sellprice', 'lastcost_as_number', 'listprice' ],
33
  profile => {profile => { listprice => 'listprice_as_number' },
34
              class   => 'SL::DB::Part',},
35 35
);
36 36
$csv->parse;
37 37

  
......
49 49
EOL
50 50
  sep_char => ',',
51 51
  quote_char => "'",
52
  profile => { listprice => 'listprice_as_number' },
53
  class  => 'SL::DB::Part',
52
  profile => {profile => { listprice => 'listprice_as_number' },
53
              class   => 'SL::DB::Part',}
54 54
);
55 55
$csv->parse;
56 56
is scalar @{ $csv->get_objects }, 1, 'auto header works';
......
64 64
;;description;sellprice;lastcost_as_number;
65 65
#####;Puppy;Kaffee;0.12;12,2;1,5234
66 66
EOL
67
  class  => 'SL::DB::Part',
67
  profile => {class  => 'SL::DB::Part'},
68 68
);
69 69
$csv->parse;
70 70
is scalar @{ $csv->get_objects }, 1, 'bozo header doesn\'t blow things up';
......
77 77
Kaffee;;0.12;12,2;1,5234
78 78
Beer;1123245;0.12;12,2;1,5234
79 79
EOL
80
  class  => 'SL::DB::Part',
80
  profile => {class  => 'SL::DB::Part'},
81 81
);
82 82
$csv->parse;
83 83
is scalar @{ $csv->get_objects }, 2, 'multiple objects work';
......
93 93
Beer;1123245;0.12;1.5234
94 94
EOL
95 95
  numberformat => '1,000.00',
96
  class  => 'SL::DB::Part',
96
  profile => {class  => 'SL::DB::Part'},
97 97
);
98 98
$csv->parse;
99 99
is $csv->get_objects->[0]->lastcost, '1221.52', 'formatnumber';
......
107 107
Beer;1123245;0.12;1.5234
108 108
EOL
109 109
  numberformat => '1,000.00',
110
  class  => 'SL::DB::Part',
110
  profile => {class  => 'SL::DB::Part'},
111 111
);
112 112
is $csv->parse, undef, 'broken csv header won\'t get parsed';
113 113

  
......
120 120
Beer;1123245;0.12;1.5234
121 121
EOL
122 122
  numberformat => '1,000.00',
123
  class  => 'SL::DB::Part',
123
  profile => {class  => 'SL::DB::Part'},
124 124
);
125 125
is $csv->parse, undef, 'broken csv content won\'t get parsed';
126 126
is_deeply $csv->errors, [ '"Kaf"fee";;0.12;1,221.52'."\n", 2023, 'EIQ - QUO character not allowed', 5, 2 ], 'error';
......
136 136
EOL
137 137
  numberformat => '1,000.00',
138 138
  ignore_unknown_columns => 1,
139
  class  => 'SL::DB::Part',
139
  profile => {class  => 'SL::DB::Part'},
140 140
);
141 141
$csv->parse;
142 142
is $csv->get_objects->[0]->lastcost, '1221.52', 'ignore_unkown_columns works';
......
150 150
Beer;1123245;0.12;1.5234;16 %
151 151
EOL
152 152
  numberformat => '1,000.00',
153
  class  => 'SL::DB::Part',
154 153
  profile => {
155
    buchungsgruppe => "buchungsgruppen.description",
154
    profile => {buchungsgruppe => "buchungsgruppen.description"},
155
    class  => 'SL::DB::Part',
156 156
  }
157 157
);
158 158
$csv->parse;
......
169 169
Beer;1123245;0.12;1.5234;
170 170
EOL
171 171
  numberformat => '1,000.00',
172
  class  => 'SL::DB::Part',
173 172
  profile => {
174
    make_1 => "makemodels.0.make",
175
    model_1 => "makemodels.0.model",
176
  }
173
    profile => {
174
      make_1 => "makemodels.0.make",
175
      model_1 => "makemodels.0.model",
176
    },
177
    class  => 'SL::DB::Part',
178
  },
177 179
);
178 180
$csv->parse;
179 181
my @mm = $csv->get_objects->[0]->makemodel;
......
189 191
 Kaffee;;0.12;1,221.52;213;Chair 0815;523;Table 15
190 192
EOL
191 193
  numberformat => '1,000.00',
192
  class  => 'SL::DB::Part',
193 194
  profile => {
194
    make_1 => "makemodels.0.make",
195
    model_1 => "makemodels.0.model",
196
    make_2 => "makemodels.1.make",
197
    model_2 => "makemodels.1.model",
195
    profile => {
196
      make_1 => "makemodels.0.make",
197
      model_1 => "makemodels.0.model",
198
      make_2 => "makemodels.1.make",
199
      model_2 => "makemodels.1.model",
200
    },
201
    class  => 'SL::DB::Part',
198 202
  }
199 203
);
200 204
$csv->parse;
......
215 219
description;partnumber;sellprice;lastcost_as_number;buchungsgruppe;
216 220
EOL
217 221
  numberformat => '1,000.00',
218
  class  => 'SL::DB::Part',
219 222
  profile => {
220
    buchungsgruppe => "buchungsgruppen.1.description",
223
    profile => {buchungsgruppe => "buchungsgruppen.1.description"},
224
    class  => 'SL::DB::Part',
221 225
  }
222 226
);
223 227
is $csv->parse, undef, 'wrong profile gets rejected';
......
235 239
  numberformat => '1,000.00',
236 240
  ignore_unknown_columns => 1,
237 241
  strict_profile => 1,
238
  class  => 'SL::DB::Part',
239 242
  profile => {
240
    lastcost => 'lastcost_as_number',
243
    profile => {lastcost => 'lastcost_as_number'},
244
    class  => 'SL::DB::Part',
241 245
  }
242 246
);
243 247
$csv->parse;
......
254 258
EOL
255 259
  numberformat => '1,000.00',
256 260
  strict_profile => 1,
257
  class  => 'SL::DB::Part',
258 261
  profile => {
259
    lastcost => 'lastcost_as_number',
262
    profile => {lastcost => 'lastcost_as_number'},
263
    class  => 'SL::DB::Part',
260 264
  }
261 265
);
262 266
$csv->parse;
......
268 272
$csv = SL::Helper::Csv->new(
269 273
  file   => \"Kaffee",
270 274
  header => [ 'description' ],
271
  class  => 'SL::DB::Part',
275
  profile => {class  => 'SL::DB::Part'},
272 276
);
273 277
$csv->parse;
274 278
is_deeply $csv->get_data, [ { description => 'Kaffee' } ], 'eol bug at the end of files';
......
277 281

  
278 282
$csv = SL::Helper::Csv->new(
279 283
  file   => \"Description\nKaffee",
280
  class  => 'SL::DB::Part',
281 284
  case_insensitive_header => 1,
282
  profile => { description => 'description' },
285
  profile => {profile => { description => 'description' }, class  => 'SL::DB::Part'},
283 286
);
284 287
$csv->parse;
285 288
is_deeply $csv->get_data, [ { description => 'Kaffee' } ], 'case insensitive header from csv works';
......
289 292
$csv = SL::Helper::Csv->new(
290 293
  file   => \"Kaffee",
291 294
  header => [ 'Description' ],
292
  class  => 'SL::DB::Part',
293 295
  case_insensitive_header => 1,
294
  profile => { description => 'description' },
296
  profile => {profile => { description => 'description' }, class  => 'SL::DB::Part'},
295 297
);
296 298
$csv->parse;
297 299
is_deeply $csv->get_data, [ { description => 'Kaffee' } ], 'case insensitive header as param works';
......
300 302

  
301 303
$csv = SL::Helper::Csv->new(
302 304
  file   => \"\x{EF}\x{BB}\x{BF}description\nKaffee",
303
  class  => 'SL::DB::Part',
305
  profile => {class  => 'SL::DB::Part'},
304 306
  encoding => 'utf8',
305 307
);
306 308
$csv->parse;
......
356 358
is_deeply $csv->get_data, [ { cvar_Groundhog => 'Phil' } ], 'using empty path to get cvars working';
357 359
ok $csv->get_objects->[0], '...and not destorying the objects';
358 360

  
361
$csv = SL::Helper::Csv->new(
362
  file   => \"description\nKaffee",
363
);
364
$csv->parse;
365
is_deeply $csv->get_data, [ { description => 'Kaffee' } ], 'without profile and class works';
366

  
359 367
# vim: ft=perl

Auch abrufbar als: Unified diff