use Products;
use OtherParents;
-our $VERSION = "1.003";
+our $VERSION = "1.004";
=head1 NAME
parent=-1
ignore_missing=1
reset_images=0
+ reset_files=0
reset_steps=0
# done by the importer
=item *
-C<ignore_missing> - set to 0 to error on missing image files.
-Default: 1.
+C<ignore_missing> - set to 0 to error on missing image or article
+files. Default: 1.
=item *
=item *
+C<reset_files> - set to true to delete all files from an article
+before adding the imported files.
+
+=item *
+
C<reset_steps> - set to true to delete all step parents from an
article before adding the imported steps.
}
$self->{ignore_missing} = $importer->cfg_entry("ignore_missing", 1);
$self->{reset_images} = $importer->cfg_entry("reset_images", 0);
+ $self->{reset_files} = $importer->cfg_entry("reset_files", 0);
$self->{reset_steps} = $importer->cfg_entry("reset_steps", 0);
return $self;
$leaf->remove_images($importer->cfg);
$importer->info(" $leaf->{id}: Reset images");
}
+ if ($self->{reset_files}) {
+ $leaf->remove_files($importer->cfg);
+ $importer->info(" $leaf->{id}: Reset files");
+ }
if ($self->{reset_steps}) {
my @steps = OtherParents->getBy(childId => $leaf->{id});
for my $step (@steps) {
or die join(", ",map "$_: $errors{$_}", keys %errors), "\n";
$importer->info(" $leaf->{id}: Add image '$file'");
}
+ $self->_add_files($importer, $entry, $leaf);
for my $step_index (1 .. 10) {
my $step_id = $entry->{"step$step_index"};
$step_id
$importer->event(endrow => { leaf => $leaf });
}
+sub _add_files {
+ my ($self, $importer, $entry, $leaf) = @_;
+
+ my %named_files = map { $_->name => $_ } grep $_->name ne '', $leaf->files;
+
+ for my $file_index (1 .. 10) {
+ my %opts;
+
+ my $found = 0;
+ for my $key (qw/name displayName storage description forSale download requireUser notes hide_from_list category/) {
+ my $fkey = "file${file_index}_$key";
+ if (defined $entry->{$fkey}) {
+ $opts{$key} = $entry->{$fkey};
+ $found = 1;
+ }
+ }
+
+ my $filename = $entry->{"file${file_index}_file"};
+ if ($filename) {
+ my $full_file = $importer->find_file($filename);
+
+ unless ($full_file) {
+ $self->{ignore_missing}
+ and next;
+ die "File '$filename' not found for file$file_index\n";
+ }
+
+ $opts{filename} = $full_file;
+ $found = 1;
+ }
+
+ $found
+ or next;
+
+ my $file;
+ if ($opts{name}) {
+ $file = $named_files{$opts{name}};
+ }
+
+ if (!$file && !$opts{filename}) {
+ die "No file${file_index}_file supplied but other file${file_index}_* field supplied\n";
+ }
+
+ if ($filename && !$opts{displayName}) {
+ ($opts{displayName}) = $filename =~ /([^\\\/:]+)$/
+ or die "Cannot create displayName for $filename\n";
+ }
+
+ if ($file) {
+ my @warnings;
+ $file->update
+ (
+ _actor => $importer->actor,
+ _warnings => \@warnings,
+ %opts,
+ );
+
+ $importer->info(" $leaf->{id}: Update file '".$file->displayName ."'");
+ }
+ else {
+ # this dies on failure
+ $file = $leaf->add_file
+ (
+ $importer->cfg,
+ %opts,
+ store => 1,
+ );
+
+
+ $importer->info(" $leaf->{id}: Add file '$filename'");
+ }
+ }
+}
+
=item xform_entry()
Called by row() to perform an extra data transformation needed.
=item *
-source - type of input format, default and currently only XLS.
+source - type of input format, default and currently C<XLS> or C<CSV>.
=item *
target - type of output record, default Product, can currently be
-Article or Product.
+C<Article> or C<Product>.
=item *
=item *
-ignore_missing - ignore missing image files. Default: 1.
+update_only - if true, records are only updated, the summary, body and
+description fields are no longer populated from title, title is no
+longer required to be mapped, and codes defaults to true. If
+C<code_field> isn't specified the first mapped field from C<id> or
+C<linkAlias> is selected (or C<product_code> for products)
+
+=item *
+
+ignore_missing - ignore missing image and article files. Default: 1.
=item *
=item *
+reset_files - reset files for an article being imported. Default: 0.
+
+=item *
+
reset_steps - reset step parents for an article being imported. Default: 0.
=back
=item *
+C<< file1_file >> .. C<< file10_file >> - name of an article file to
+attach to the article.
+
+=item *
+
+C<< file1I<N>_name >>, C<< file1I<N>_displayName >>, C<<
+file1I<N>_storage >>, C<< file1I<N>_description >>, C<<
+file1I<N>_forSale >>, C<< file1I<N>_download >>, C<<
+file1I<N>_requireUser >>, C<< file1I<N>_notes >>, C<<
+file1I<N>_hide_from_list >>, C<< file1I<N>_category >> - set other
+file fields.
+
+=item *
+
step1 .. step10 - step parent id or linkAlias
=item *
use File::Spec;
use File::Temp;
-use Test::More tests => 5;
+use Test::More tests => 41;
BEGIN {
unshift @INC, File::Spec->catdir(BSE::Test::base_dir(), "cgi-bin", "modules");
[import profile simpleupdate$when]
map_linkAlias=1
map_body=2
+map_file1_file=3
+map_image1_file=4
source=CSV
target=Article
update_only=1
sep_char=\\t
+file_path=t
+ignore_missing=0
+
+[import profile completefile$when]
+map_linkAlias=1
+map_file1_file=2
+map_file1_name=3
+map_file1_displayName=4
+map_file1_storage=5
+map_file1_description=6
+map_file1_forSale=7
+map_file1_download=8
+map_file1_requireUser=9
+map_file1_notes=10
+map_file1_hide_from_list=11
+skiplines=0
+file_path=t
+ignore_missing=0
+update_only=1
+source=CSV
+target=Article
+
+[import profile updatefile$when]
+map_linkAlias=1
+map_file1_name=2
+map_file1_description=3
+skiplines=0
+file_path=t
+ignore_missing=0
+update_only=1
+source=CSV
+target=Article
+
+[import profile updatefileb$when]
+map_linkAlias=1
+map_file1_name=2
+map_file1_file=3
+skiplines=0
+file_path=t/data
+ignore_missing=0
+update_only=1
+source=CSV
+target=Article
+
CFG
{
my $testa = bse_make_article(cfg => $cfg, title => "test updates",
linkAlias => "alias$when");
- my $fh = File::Temp->new;
- my $filename = $fh->filename;
- print $fh <<EOS;
-linkAlias\tbody
+ {
+ my $fh = File::Temp->new;
+ my $filename = $fh->filename;
+ print $fh <<EOS;
+linkAlias\tbody\tfile1_file\timage1_file
"alias$when"\t"This is the body text with multiple lines
-Yes, multiple lines with CSV!"
+Yes, multiple lines with CSV!"\tt00smoke.t\tdata/t101.jpg
+EOS
+ close $fh;
+ my $imp = BSE::Importer->new(cfg => $cfg, profile => "simpleupdate$when", callback => sub { note @_ });
+ $imp->process($filename);
+ my $testb = Articles->getByPkey($testa->id);
+ like($testb->body, qr/This is the body/, "check the body is updated");
+ my @images = $testb->images;
+ is(@images, 1, "have an image");
+ like($images[0]->image, qr/t101\.jpg/, "check file name");
+ is(-s $images[0]->full_filename, -s "t/data/t101.jpg",
+ "check size matches source");
+
+ my @files = $testb->files;
+ is(@files, 1, "should be 1 file");
+ is($files[0]->displayName, "t00smoke.t", "check display name");
+ is(-s $files[0]->full_filename, -s "t/t00smoke.t", "check size");
+ }
+
+ SKIP:
+ {
+ my $fh = File::Temp->new;
+ my $filename = $fh->filename;
+ print $fh <<EOS;
+"alias$when",t00smoke.t,test,"A Test File.txt",local,"A test file from BSE",1,1,1,"Some Notes",1
EOS
- close $fh;
- my $imp = BSE::Importer->new(cfg => $cfg, profile => "simpleupdate$when", callback => sub { note @_ });
- $imp->process($filename);
- my $testb = Articles->getByPkey($testa->id);
- like($testb->body, qr/This is the body/, "check the body is updated");
+ close $fh;
+ my $imp = BSE::Importer->new(cfg => $cfg, profile => "completefile$when", callback => sub { note @_ });
+ $imp->process($filename);
+ my $testb = Articles->getByPkey($testa->id);
+
+ my ($file) = grep $_->name eq "test", $testb->files;
+ ok($file, "found the file with name 'test'")
+ or skip "File not found", 9;
+ is(-s $file->full_filename, -s "t/t00smoke.t", "check size");
+ is($file->displayName, "A Test File.txt", "displayName");
+ is($file->storage, "local", "storage");
+ is($file->description, "A test file from BSE", "description");
+ is($file->forSale, 1, "forSale");
+ is($file->download, 1, "download");
+ is($file->requireUser, 1, "requireUser");
+ is($file->notes, "Some Notes", "notes");
+ is($file->hide_from_list, 1, "hide_from_list");
+ }
+
+ SKIP:
+ {
+ my $fh = File::Temp->new;
+ my $filename = $fh->filename;
+ print $fh <<EOS;
+"alias$when",test,"New description"
+EOS
+ close $fh;
+ my $imp = BSE::Importer->new(cfg => $cfg, profile => "updatefile$when", callback => sub { note @_ });
+ $imp->process($filename);
+ my $testb = Articles->getByPkey($testa->id);
+
+ my ($file) = grep $_->name eq "test", $testb->files;
+ ok($file, "found the updated file with name 'test'")
+ or skip "File not found", 9;
+ is($file->description, "New description", "description");
+ # other fields should be unchanged
+ is(-s $file->full_filename, -s "t/t00smoke.t", "check size");
+ is($file->displayName, "A Test File.txt", "displayName");
+ is($file->storage, "local", "storage");
+ is($file->forSale, 1, "forSale");
+ is($file->download, 1, "download");
+ is($file->requireUser, 1, "requireUser");
+ is($file->notes, "Some Notes", "notes");
+ is($file->hide_from_list, 1, "hide_from_list");
+ }
+
+ SKIP:
+ {
+ my $fh = File::Temp->new;
+ my $filename = $fh->filename;
+ print $fh <<EOS;
+"alias$when",test,t101.jpg
+EOS
+ close $fh;
+ my $imp = BSE::Importer->new(cfg => $cfg, profile => "updatefileb$when", callback => sub { note @_ });
+ $imp->process($filename);
+ my $testb = Articles->getByPkey($testa->id);
+
+ my ($file) = grep $_->name eq "test", $testb->files;
+ ok($file, "found the updated file with name 'test'")
+ or skip "File not found", 9;
+ is(-s $file->full_filename, -s "t/data/t101.jpg", "check size");
+ is($file->displayName, "t101.jpg", "new displayName");
+ # other fields should be unchanged
+ is($file->storage, "local", "storage");
+ is($file->description, "New description", "description");
+ is($file->forSale, 1, "forSale");
+ is($file->download, 1, "download");
+ is($file->requireUser, 1, "requireUser");
+ is($file->notes, "Some Notes", "notes");
+ is($file->hide_from_list, 1, "hide_from_list");
+ }
END {
$testa->remove($cfg) if $testa;