1 package SL::File::Backend::Filesystem;
 
   5 use parent qw(SL::File::Backend);
 
   9 use File::Path qw(make_path);
 
  16   my ($self, %params) = @_;
 
  17   die "no dbfile in backend delete" unless $params{dbfile};
 
  18   my $backend_data = $params{dbfile}->backend_data;
 
  19   $backend_data    = 0                               if $params{last};
 
  20   $backend_data    = $params{dbfile}->backend_data-1 if $params{all_but_notlast};
 
  22   if ($backend_data > 0 ) {
 
  23     for my $version ( 1..$backend_data) {
 
  24       my $file_path = $self->_filesystem_path($params{dbfile},$version);
 
  27     if ($params{all_but_notlast}) {
 
  28       my $from = $self->_filesystem_path($params{dbfile},$params{dbfile}->backend_data);
 
  29       my $to   = $self->_filesystem_path($params{dbfile},1);
 
  30       die "file not exists in backend delete" unless -f $from;
 
  32       $params{dbfile}->backend_data(1);
 
  34       $params{dbfile}->backend_data(0);
 
  35       my $dir_path = $self->_filesystem_path($params{dbfile});
 
  39     my $file_path = $self->_filesystem_path($params{dbfile},$params{dbfile}->backend_data);
 
  40     die "file not exists in backend delete" unless -f $file_path;
 
  42     $params{dbfile}->backend_data($params{dbfile}->backend_data-1);
 
  51   my ($self, %params) = @_;
 
  52   die 'dbfile not exists' unless $params{dbfile};
 
  53   my $dbfile = $params{dbfile};
 
  54   die 'no file contents' unless $params{file_path} || $params{file_contents};
 
  55   $dbfile->backend_data(0) unless $dbfile->backend_data;
 
  56   $dbfile->backend_data($dbfile->backend_data*1+1);
 
  59   my $tofile = $self->_filesystem_path($dbfile);
 
  60   if ($params{file_path} && -f $params{file_path}) {
 
  61     File::Copy::copy($params{file_path}, $tofile);
 
  63   elsif ($params{file_contents}) {
 
  64     open(OUT, "> " . $tofile);
 
  65     print OUT $params{file_contents};
 
  71 sub get_version_count {
 
  72   my ($self, %params) = @_;
 
  73   die "no dbfile" unless $params{dbfile};
 
  74   return $params{dbfile}->backend_data * 1;
 
  78   my ($self, %params) = @_;
 
  79   die "no dbfile" unless $params{dbfile};
 
  80   die "unknown version" if $params{version} &&
 
  81                           ($params{version} < 0 || $params{version} > $params{dbfile}->backend_data);
 
  82   my $path = $self->_filesystem_path($params{dbfile}, $params{version});
 
  84   die "No file found at $path. Expected: $params{dbfile}{file_name}, file.id: $params{dbfile}{id}" if !-f $path;
 
  87   my $dt = DateTime->from_epoch(epoch => $st[9])->clone();
 
  92   my ($self, %params) = @_;
 
  93   die "no dbfile" unless $params{dbfile};
 
  94   my $path = $self->_filesystem_path($params{dbfile},$params{version});
 
  95   die "no file in backend get_filepath" if !-f $path;
 
 100   my ($self, %params) = @_;
 
 101   my $path = $self->get_filepath(%params);
 
 102   return "" unless $path;
 
 103   my $contents = File::Slurp::read_file($path);
 
 108   return 0 unless $::instance_conf->get_doc_files;
 
 109   return 0 unless $::lx_office_conf{paths}->{document_path};
 
 110   return 0 unless -d $::lx_office_conf{paths}->{document_path};
 
 114 sub sync_from_backend {
 
 115   my ($self, %params) = @_;
 
 116   my @query = (file_type => $params{file_type});
 
 117   push @query, (file_name => $params{file_name}) if $params{file_name};
 
 118   push @query, (mime_type => $params{mime_type}) if $params{mime_type};
 
 119   push @query, (source    => $params{source})    if $params{source};
 
 121   my $sortby = $params{sort_by} || 'itime DESC,file_name ASC';
 
 123   my @files = @{ SL::DB::Manager::File->get_all(query => [@query], sort_by => $sortby) };
 
 125     $main::lxdebug->message(LXDebug->DEBUG2(), "file id=" . $_->id." version=".$_->backend_data);
 
 126     my $newversion = $_->backend_data;
 
 127     for my $version ( reverse 1 .. $_->backend_data ) {
 
 128       my $path = $self->_filesystem_path($_, $version);
 
 129       $main::lxdebug->message(LXDebug->DEBUG2(), "path=".$path." exists=".( -f $path?1:0));
 
 131       $newversion = $version - 1;
 
 133     $main::lxdebug->message(LXDebug->DEBUG2(), "newversion=".$newversion." version=".$_->backend_data);
 
 134     if ( $newversion < $_->backend_data ) {
 
 135       $_->backend_data($newversion);
 
 136       $_->save   if $newversion >  0;
 
 137       $_->delete if $newversion <= 0;
 
 147 sub _filesystem_path {
 
 148   my ($self, $dbfile, $version) = @_;
 
 150   die "No files backend enabled" unless $::instance_conf->get_doc_files || $::lx_office_conf{paths}->{document_path};
 
 152   # use filesystem with depth 3
 
 153   $version    = $dbfile->backend_data if !$version || $version < 1 || $version > $dbfile->backend_data;
 
 154   my $iddir   = sprintf("%04d", $dbfile->id % 1000);
 
 155   my $path    = File::Spec->catdir($::lx_office_conf{paths}->{document_path}, $::auth->client->{id}, $iddir, $dbfile->id);
 
 157     File::Path::make_path($path, { chmod => 0770 });
 
 159   return $path if !$version;
 
 160   return File::Spec->catdir($path, $dbfile->id . '_' . $version);
 
 173 SL::File::Backend::Filesystem  - Filesystem class for file storage backend
 
 177 See the synopsis of L<SL::File::Backend>.
 
 181 This specific storage backend use a Filesystem which is only accessed by this interface.
 
 182 This is the big difference to the Webdav backend where the files can be accessed without the control of that backend.
 
 183 This backend use the database id of the SL::DB::File object as filename. The filesystem has up to 1000 subdirectories
 
 184 to store the files not to flat in the filesystem. In this Subdirectories for each file an additional subdirectory exists
 
 185 for the versions of this file.
 
 187 The Versioning is done via a Versionnumber which is incremented by one for each version.
 
 188 So the Version 2 of the file with the database id 4 is stored as path {root}/0004/4/4_2.
 
 193 See methods of L<SL::File::Backend>.
 
 201 Martin Helmling E<lt>martin.helmling@opendynamic.deE<gt>