]> wagnertech.de Git - mfinanz.git/blobdiff - SL/File/Backend/Filesystem.pm
Merge branch 'master' of http://wagnertech.de/git/mfinanz
[mfinanz.git] / SL / File / Backend / Filesystem.pm
index 92292838090ca6e28121644edeafdaac3af60161..d2ff9d3edb5f4a307f57bf697d417d97f33f12f9 100644 (file)
@@ -4,9 +4,16 @@ use strict;
 
 use parent qw(SL::File::Backend);
 use SL::DB::File;
+use SL::DB::FileVersion;
+
+use Carp;
+use List::Util qw(first);
+
 use File::Copy;
 use File::Slurp;
+use File::stat;
 use File::Path qw(make_path);
+use UUID::Tiny ':std';
 
 #
 # public methods
@@ -15,46 +22,30 @@ use File::Path qw(make_path);
 sub delete {
   my ($self, %params) = @_;
   die "no dbfile in backend delete" unless $params{dbfile};
-  my $last_version  = $params{dbfile}->backend_data;
-  my $first_version = 1;
-  $last_version     = 0                               if $params{last};
-  $last_version     = $params{dbfile}->backend_data-1 if $params{all_but_notlast};
-  $last_version     = $params{version}                if $params{version};
-  $first_version    = $params{version}                if $params{version};
-
-  if ($last_version > 0 ) {
-    for my $version ( $first_version..$last_version) {
-      my $file_path = $self->_filesystem_path($params{dbfile},$version);
-      unlink($file_path);
-    }
-    if ($params{version}) {
-      for my $version ( $last_version+1 .. $params{dbfile}->backend_data) {
-        my $from = $self->_filesystem_path($params{dbfile},$version);
-        my $to   = $self->_filesystem_path($params{dbfile},$version - 1);
-        die "file not exists in backend delete" unless -f $from;
-        rename($from,$to);
-      }
-      $params{dbfile}->backend_data($params{dbfile}->backend_data-1);
-    }
-    elsif ($params{all_but_notlast}) {
-      my $from = $self->_filesystem_path($params{dbfile},$params{dbfile}->backend_data);
-      my $to   = $self->_filesystem_path($params{dbfile},1);
-      die "file not exists in backend delete" unless -f $from;
-      rename($from,$to);
-      $params{dbfile}->backend_data(1);
+
+  my @versions_to_delete;
+  if ($params{file_version}) {
+    croak "file_version has to be of type SL::DB::FileVersion"
+      unless ref $params{file_version} eq 'SL::DB::FileVersion';
+    @versions_to_delete = ($params{file_version});
+  } else {
+    my @versions = @{$params{dbfile}->file_versions_sorted};
+    if ($params{last}) {
+      my $last = pop @versions;
+      @versions_to_delete = ($last);
+    } elsif ($params{all_but_notlast}) {
+      pop @versions; # remove last
+      @versions_to_delete = @versions;
     } else {
-      $params{dbfile}->backend_data(0);
-    }
-    unless ($params{dbfile}->backend_data) {
-      my $dir_path = $self->_filesystem_path($params{dbfile});
-      rmdir($dir_path);
+      @versions_to_delete = @versions;
     }
-  } else {
-    my $file_path = $self->_filesystem_path($params{dbfile},$params{dbfile}->backend_data);
-    die "file not exists in backend delete" unless -f $file_path;
-    unlink($file_path);
-    $params{dbfile}->backend_data($params{dbfile}->backend_data-1);
   }
+
+  foreach my $version (@versions_to_delete) {
+    unlink($version->get_system_location());
+    $version->delete;
+  }
+
   return 1;
 }
 
@@ -63,42 +54,64 @@ sub rename {
 
 sub save {
   my ($self, %params) = @_;
-  die 'dbfile not exists' unless $params{dbfile};
-  my $dbfile = $params{dbfile};
-  die 'no file contents' unless $params{file_path} || $params{file_contents};
-  $dbfile->backend_data(0) unless $dbfile->backend_data;
-  $dbfile->backend_data($dbfile->backend_data*1+1);
-  $dbfile->save->load;
-
-  my $tofile = $self->_filesystem_path($dbfile);
+
+  die 'dbfile not exists' unless ref $params{dbfile} eq 'SL::DB::File';
+  die 'no file contents'  unless $params{file_path} || $params{file_contents};
+
+  my $dbfile = delete $params{dbfile};
+
+  # Do not save and do not create a new version of the document if file size of last version is the same.
+  if ($dbfile->source eq 'created' && $self->get_version_count(dbfile => $dbfile)) {
+    my $new_file_size  = $params{file_path} ? stat($params{file_path})->size : length($params{file_contents});
+    my $last_file_size = stat($self->_filesystem_path($dbfile))->size;
+
+    return 1 if $last_file_size == $new_file_size;
+  }
+
+  my @versions = @{$dbfile->file_versions_sorted};
+  my $new_version_number = scalar @versions ? $versions[-1]->version + 1 : 1;
+
+  my $tofile = $self->_filesystem_path($dbfile, $new_version_number);
   if ($params{file_path} && -f $params{file_path}) {
     File::Copy::copy($params{file_path}, $tofile);
-  }
-  elsif ($params{file_contents}) {
+  } elsif ($params{file_contents}) {
     open(OUT, "> " . $tofile);
     print OUT $params{file_contents};
     close(OUT);
   }
+
+  # save file version
+  my $doc_path = $::lx_office_conf{paths}->{document_path};
+  my $rel_file = $tofile;
+  $rel_file    =~ s/$doc_path//;
+  my $fv = SL::DB::FileVersion->new(
+    file_id       => $dbfile->id,
+    version       => $new_version_number,
+    file_location => $rel_file,
+    doc_path      => $doc_path,
+    backend       => 'Filesystem',
+    guid          => create_uuid_as_string(UUID_V4),
+  )->save;
+
+  if ($params{mtime}) {
+    utime($params{mtime}, $params{mtime}, $tofile);
+  }
   return 1;
 }
 
 sub get_version_count {
   my ($self, %params) = @_;
   die "no dbfile" unless $params{dbfile};
-  return $params{dbfile}->backend_data * 1;
+  my $file_id = $params{dbfile}->id;
+  return 0 unless defined $file_id;
+  return SL::DB::Manager::FileVersion->get_all_count(where => [file_id => $file_id]);
 }
 
 sub get_mtime {
   my ($self, %params) = @_;
-  die "no dbfile" unless $params{dbfile};
-  die "unknown version" if $params{version} &&
-                          ($params{version} < 0 || $params{version} > $params{dbfile}->backend_data);
-  my $path = $self->_filesystem_path($params{dbfile}, $params{version});
-
-  die "No file found at $path. Expected: $params{dbfile}{file_name}, file.id: $params{dbfile}{id}" if !-f $path;
+  my $path = $self->get_filepath(%params);
 
-  my @st = stat($path);
-  my $dt = DateTime->from_epoch(epoch => $st[9])->clone();
+  my $dt = DateTime->from_epoch(epoch => stat($path)->mtime, time_zone => $::locale->get_local_time_zone()->name, locale => $::lx_office_conf{system}->{language})->clone();
   return $dt;
 }
 
@@ -106,7 +119,9 @@ sub get_filepath {
   my ($self, %params) = @_;
   die "no dbfile" unless $params{dbfile};
   my $path = $self->_filesystem_path($params{dbfile},$params{version});
-  die "no file in backend get_filepath" if !-f $path;
+
+  die "No file found at $path. Expected: $params{dbfile}{file_name}, file.id: $params{dbfile}{id}" if !-f $path;
+
   return $path;
 }
 
@@ -126,32 +141,7 @@ sub enabled {
 }
 
 sub sync_from_backend {
-  my ($self, %params) = @_;
-  my @query = (file_type => $params{file_type});
-  push @query, (file_name => $params{file_name}) if $params{file_name};
-  push @query, (mime_type => $params{mime_type}) if $params{mime_type};
-  push @query, (source    => $params{source})    if $params{source};
-
-  my $sortby = $params{sort_by} || 'itime DESC,file_name ASC';
-
-  my @files = @{ SL::DB::Manager::File->get_all(query => [@query], sort_by => $sortby) };
-  for (@files) {
-    $main::lxdebug->message(LXDebug->DEBUG2(), "file id=" . $_->id." version=".$_->backend_data);
-    my $newversion = $_->backend_data;
-    for my $version ( reverse 1 .. $_->backend_data ) {
-      my $path = $self->_filesystem_path($_, $version);
-      $main::lxdebug->message(LXDebug->DEBUG2(), "path=".$path." exists=".( -f $path?1:0));
-      last if -f $path;
-      $newversion = $version - 1;
-    }
-    $main::lxdebug->message(LXDebug->DEBUG2(), "newversion=".$newversion." version=".$_->backend_data);
-    if ( $newversion < $_->backend_data ) {
-      $_->backend_data($newversion);
-      $_->save   if $newversion >  0;
-      $_->delete if $newversion <= 0;
-    }
-  }
-
+  die "Not implemented";
 }
 
 #
@@ -163,14 +153,20 @@ sub _filesystem_path {
 
   die "No files backend enabled" unless $::instance_conf->get_doc_files || $::lx_office_conf{paths}->{document_path};
 
+  unless ($version) {
+    my $file_version = SL::DB::Manager::FileVersion->get_first(
+      where   => [file_id => $dbfile->id],
+      sort_by => 'version DESC'
+    ) or die "Could not find a file version for file with id " . $dbfile->id;
+    $version = $file_version->version;
+  }
+
   # use filesystem with depth 3
-  $version    = $dbfile->backend_data if !$version || $version < 1 || $version > $dbfile->backend_data;
   my $iddir   = sprintf("%04d", $dbfile->id % 1000);
   my $path    = File::Spec->catdir($::lx_office_conf{paths}->{document_path}, $::auth->client->{id}, $iddir, $dbfile->id);
   if (!-d $path) {
     File::Path::make_path($path, { chmod => 0770 });
   }
-  return $path if !$version;
   return File::Spec->catdir($path, $dbfile->id . '_' . $version);
 }