1 package SL::File::Backend::Webdav;
 
   5 use parent qw(SL::File::Backend);
 
   8 use SL::System::Process;
 
  12 use File::Path qw(make_path);
 
  13 use File::MimeInfo::Magic;
 
  21   my ($self, %params) = @_;
 
  22   $main::lxdebug->message(LXDebug->DEBUG2(), "del in backend " . $self . "  file " . $params{dbfile});
 
  23   $main::lxdebug->message(LXDebug->DEBUG2(), "file id=" . $params{dbfile}->id * 1);
 
  24   return 0 unless $params{dbfile};
 
  25   my ($file_path, undef, undef) = $self->webdav_path($params{dbfile});
 
  31   my ($self, %params) = @_;
 
  32   return 0 unless $params{dbfile};
 
  33   my (undef, $oldwebdavname) = split(/:/, $params{dbfile}->location, 2);
 
  34   my ($tofile, $basepath, $basename) = $self->webdav_path($params{dbfile});
 
  35   my $fromfile = File::Spec->catfile($basepath, $oldwebdavname);
 
  36   $main::lxdebug->message(LXDebug->DEBUG2(), "renamefrom=" . $fromfile . " to=" . $tofile);
 
  37   move($fromfile, $tofile);
 
  41   my ($self, %params) = @_;
 
  42   die 'dbfile not exists' unless $params{dbfile};
 
  43   $main::lxdebug->message(LXDebug->DEBUG2(), "in backend " . $self . "  file " . $params{dbfile});
 
  44   $main::lxdebug->message(LXDebug->DEBUG2(), "file id=" . $params{dbfile}->id);
 
  45   my $dbfile = $params{dbfile};
 
  46   die 'no file contents' unless $params{file_path} || $params{file_contents};
 
  48   if ($params{dbfile}->id * 1 == 0) {
 
  50     # new element: need id for file
 
  51     $params{dbfile}->save;
 
  53   my ($tofile, undef, $basename) = $self->webdav_path($params{dbfile});
 
  54   if ($params{file_path} && -f $params{file_path}) {
 
  55     copy($params{file_path}, $tofile);
 
  57   elsif ($params{file_contents}) {
 
  58     open(OUT, "> " . $tofile);
 
  59     print OUT $params{file_contents};
 
  65 sub get_version_count {
 
  66   my ($self, %params) = @_;
 
  67   die "no dbfile" unless $params{dbfile};
 
  73   my ($self, %params) = @_;
 
  74   die "no dbfile" unless $params{dbfile};
 
  75   $main::lxdebug->message(LXDebug->DEBUG2(), "version=" .$params{version});
 
  76   my ($path, undef, undef) = $self->webdav_path($params{dbfile});
 
  77   die "No file found in Backend: " . $path unless -f $path;
 
  78   my $dt = DateTime->from_epoch(epoch => stat($path)->mtime, time_zone => $::locale->get_local_time_zone()->name)->clone();
 
  79   $main::lxdebug->message(LXDebug->DEBUG2(), "dt=" .$dt);
 
  84   my ($self, %params) = @_;
 
  85   die "no dbfile" unless $params{dbfile};
 
  86   my ($path, undef, undef) = $self->webdav_path($params{dbfile});
 
  87   die "No file found in Backend: " . $path unless -f $path;
 
  92   my ($self, %params) = @_;
 
  93   my $path = $self->get_filepath(%params);
 
  94   return "" unless $path;
 
  95   my $contents = File::Slurp::read_file($path);
 
  99 sub sync_from_backend {
 
 100   my ($self, %params) = @_;
 
 101   return unless $params{file_type};
 
 103   $self->sync_all_locations(%params);
 
 108   return $::instance_conf->get_doc_webdav;
 
 116   sales_quotation         => 'angebote',
 
 117   sales_order             => 'bestellungen',
 
 118   request_quotation       => 'anfragen',
 
 119   purchase_order          => 'lieferantenbestellungen',
 
 120   sales_delivery_order    => 'verkaufslieferscheine',
 
 121   purchase_delivery_order => 'einkaufslieferscheine',
 
 122   credit_note             => 'gutschriften',
 
 123   invoice                 => 'rechnungen',
 
 124   purchase_invoice        => 'einkaufsrechnungen',
 
 126   service                 => 'dienstleistungen',
 
 127   assembly                => 'erzeugnisse',
 
 129   general_ledger          => 'dialogbuchungen',
 
 130   gl_transaction          => 'dialogbuchungen',
 
 131   accounts_payable        => 'kreditorenbuchungen',
 
 132   shop_image              => 'shopbilder',
 
 133   customer                => 'kunden',
 
 134   vendor                  => 'lieferanten',
 
 137 my %type_to_model = (
 
 138   sales_quotation         => 'Order',
 
 139   sales_order             => 'Order',
 
 140   request_quotation       => 'Order',
 
 141   purchase_order          => 'Order',
 
 142   sales_delivery_order    => 'DeliveryOrder',
 
 143   purchase_delivery_order => 'DeliveryOrder',
 
 144   credit_note             => 'Invoice',
 
 145   invoice                 => 'Invoice',
 
 146   purchase_invoice        => 'PurchaseInvoice',
 
 151   general_ledger          => 'GLTransaction',
 
 152   gl_transaction          => 'GLTransaction',
 
 153   accounts_payable        => 'GLTransaction',
 
 154   shop_image              => 'Part',
 
 155   customer                => 'Customer',
 
 159 my %model_to_number = (
 
 160   Order           => 'ordnumber',
 
 161   DeliveryOrder   => 'ordnumber',
 
 162   Invoice         => 'invnumber',
 
 163   PurchaseInvoice => 'invnumber',
 
 164   Part            => 'partnumber',
 
 165   Letter          => 'letternumber',
 
 166   GLTransaction   => 'reference',
 
 167   ShopImage       => 'partnumber',
 
 168   Customer        => 'customernumber',
 
 169   Vendor          => 'vendornumber',
 
 173   my ($self, $dbfile) = @_;
 
 175   #die "No webdav backend enabled" unless $::instance_conf->get_webdav;
 
 177   my $type = $type_to_path{ $dbfile->object_type };
 
 179   die "Unknown type" unless $type;
 
 181   my $number = $dbfile->backend_data;
 
 183     $number = $self->_get_number_from_model($dbfile);
 
 184     $dbfile->backend_data($number);
 
 187   $main::lxdebug->message(LXDebug->DEBUG2(), "file_name=" . $dbfile->file_name ." number=".$number);
 
 189   my @fileparts = split(/_/, $dbfile->file_name);
 
 190   my $number_ext = pop @fileparts;
 
 191   my ($maynumber, $ext) = split(/\./, $number_ext, 2);
 
 192   push @fileparts, $maynumber if $maynumber ne $number;
 
 194   my $basename = join('_', @fileparts);
 
 196   my $path = File::Spec->catdir($self->get_rootdir, "webdav", $::auth->client->{id}, $type, $number);
 
 198     File::Path::make_path($path, { chmod => 0770 });
 
 200   my $fname = $basename . '_' . $number . '_' . $dbfile->itime->strftime('%Y%m%d_%H%M%S');
 
 201   $fname .= '.' . $ext if $ext;
 
 203   $main::lxdebug->message(LXDebug->DEBUG2(), "webdav path=" . $path . " filename=" . $fname);
 
 205   return (File::Spec->catfile($path, $fname), $path, $fname);
 
 208 sub get_rootdir { SL::System::Process::exe_dir() }
 
 210 sub _get_number_from_model {
 
 211   my ($self, $dbfile) = @_;
 
 213   my $class = 'SL::DB::' . $type_to_model{ $dbfile->object_type };
 
 214   eval "require $class";
 
 215   my $obj = $class->new(id => $dbfile->object_id)->load;
 
 216   die 'no object found' unless $obj;
 
 217   my $numberattr = $model_to_number{ $type_to_model{ $dbfile->object_type } };
 
 218   return $obj->$numberattr;
 
 222 # TODO not fully imlemented and tested
 
 224 sub sync_all_locations {
 
 225   my ($self, %params) = @_;
 
 227   my %dateparms = (dateformat => 'yyyymmdd');
 
 229   foreach my $type (keys %type_to_path) {
 
 232       file_type => $params{file_type},
 
 235     my @oldfiles = @{ SL::DB::Manager::File->get_all(
 
 237           file_type => $params{file_type},
 
 243     my $path = File::Spec->catdir($self->get_rootdir, "webdav", $::auth->client->{id},$type_to_path{$type});
 
 245     if (opendir my $dir, $path) {
 
 246       foreach my $file (sort { lc $a cmp lc $b }
 
 247         map { decode("UTF-8", $_) } readdir $dir)
 
 249         next if (($file eq '.') || ($file eq '..'));
 
 254         my ($filename, $number, $date, $time_ext) = split(/_/, $fname);
 
 255         my ($time, $ext) = split(/\./, $time_ext, 2);
 
 257         $time = substr($time, 0, 2) . ':' . substr($time, 2, 2) . ':' . substr($time, 4, 2);
 
 259         #my @found = grep { $_->backend_data eq $fname } @oldfiles;
 
 260         #if (scalar(@found) > 0) {
 
 261         #  @oldfiles = grep { $_ != @found[0] } @oldfiles;
 
 264           my $dbfile = SL::DB::File->new();
 
 265           my $class  = 'SL::DB::Manager::' . $type_to_model{$type};
 
 268             $model_to_number{ $type_to_model{$type} } => $number);
 
 271             my $mime_type = File::MimeInfo::Magic::magic(File::Spec->catfile($path, $fname));
 
 273               # if filename has the suffix "pdf", but is really no pdf set mimetype for no suffix
 
 274               $mime_type = File::MimeInfo::Magic::mimetype($fname);
 
 275               $mime_type = 'application/octet-stream' if $mime_type eq 'application/pdf' || !$mime_type;
 
 278             $dbfile->assign_attributes(
 
 279               object_id   => $obj->id,
 
 280               object_type => $type,
 
 281               source      => $params{file_type} eq 'document' ? 'created' : 'uploaded',
 
 282               file_type   => $params{file_type},
 
 283               file_name   => $filename . '_' . $number . '_' . $ext,
 
 284               mime_type   => $mime_type,
 
 285               itime       => $::locale->parse_date_to_object($date . ' ' . $time, %dateparms),
 
 307 SL::File::Backend::Filesystem  - Filesystem class for file storage backend
 
 311 See the synopsis of L<SL::File::Backend>.
 
 315 This specific storage backend use a Filesystem which is only accessed by this interface.
 
 316 This is the big difference to the Webdav backend where the files can be accessed without the control of that backend.
 
 317 This backend use the database id of the SL::DB::File object as filename. The filesystem has up to 1000 subdirectories
 
 318 to store the files not to flat in the filesystem.
 
 323 See methods of L<SL::File::Backend>.
 
 331 The synchronization must be tested and a periodical task is needed to synchronize in some time periods.
 
 335 Martin Helmling E<lt>martin.helmling@opendynamic.deE<gt>