Projekt

Allgemein

Profil

Herunterladen (5,73 KB) Statistiken
| Zweig: | Markierung: | Revision:
8c7f25bc Martin Helmling
package SL::File::Backend::Filesystem;

use strict;

use parent qw(SL::File::Backend);
use SL::DB::File;
0b39fe88 Tamino Steinert
use SL::DB::FileVersion;
fe681ce4 Jan Büren
378828e9 Tamino Steinert
use Carp;
use List::Util qw(first);

8c7f25bc Martin Helmling
use File::Copy;
use File::Slurp;
c5057972 Bernd Bleßmann
use File::stat;
8c7f25bc Martin Helmling
use File::Path qw(make_path);
fe681ce4 Jan Büren
use UUID::Tiny ':std';
8c7f25bc Martin Helmling
#
# public methods
#

sub delete {
my ($self, %params) = @_;
56371b77 Martin Helmling
die "no dbfile in backend delete" unless $params{dbfile};
378828e9 Tamino Steinert
my @versions_to_delete;
ca10be4b Tamino Steinert
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});
8c7f25bc Martin Helmling
} else {
ca10be4b Tamino Steinert
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 {
@versions_to_delete = @versions;
}
8c7f25bc Martin Helmling
}

378828e9 Tamino Steinert
foreach my $version (@versions_to_delete) {
unlink($version->get_system_location());
$version->delete;
}

return 1;
8c7f25bc Martin Helmling
}

6da526ef Tamino Steinert
sub rename {
}

8c7f25bc Martin Helmling
sub save {
my ($self, %params) = @_;
e823b5d6 Jan Büren
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};
c5057972 Bernd Bleßmann
# 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;
}

378828e9 Tamino Steinert
my @versions = @{$dbfile->file_versions_sorted};
my $new_version_number = scalar @versions ? $versions[-1]->version + 1 : 1;
8c7f25bc Martin Helmling
378828e9 Tamino Steinert
my $tofile = $self->_filesystem_path($dbfile, $new_version_number);
8c7f25bc Martin Helmling
if ($params{file_path} && -f $params{file_path}) {
File::Copy::copy($params{file_path}, $tofile);
e823b5d6 Jan Büren
} elsif ($params{file_contents}) {
8c7f25bc Martin Helmling
open(OUT, "> " . $tofile);
print OUT $params{file_contents};
close(OUT);
}
0b39fe88 Tamino Steinert
# save file version
fe681ce4 Jan Büren
my $doc_path = $::lx_office_conf{paths}->{document_path};
my $rel_file = $tofile;
$rel_file =~ s/$doc_path//;
my $fv = SL::DB::FileVersion->new(
0b39fe88 Tamino Steinert
file_id => $dbfile->id,
378828e9 Tamino Steinert
version => $new_version_number,
0b39fe88 Tamino Steinert
file_location => $rel_file,
doc_path => $doc_path,
backend => 'Filesystem',
guid => create_uuid_as_string(UUID_V4),
)->save;

74d8dd6f Martin Helmling
if ($params{mtime}) {
utime($params{mtime}, $params{mtime}, $tofile);
}
8c7f25bc Martin Helmling
return 1;
}

sub get_version_count {
my ($self, %params) = @_;
die "no dbfile" unless $params{dbfile};
378828e9 Tamino Steinert
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]);
8c7f25bc Martin Helmling
}

sub get_mtime {
my ($self, %params) = @_;
378828e9 Tamino Steinert
my $path = $self->get_filepath(%params);
c5dc4974 Jan Büren
c5057972 Bernd Bleßmann
my $dt = DateTime->from_epoch(epoch => stat($path)->mtime, time_zone => $::locale->get_local_time_zone()->name, locale => $::lx_office_conf{system}->{language})->clone();
8c7f25bc Martin Helmling
return $dt;
}

sub get_filepath {
my ($self, %params) = @_;
die "no dbfile" unless $params{dbfile};
my $path = $self->_filesystem_path($params{dbfile},$params{version});
2329b45d Bernd Bleßmann
die "No file found at $path. Expected: $params{dbfile}{file_name}, file.id: $params{dbfile}{id}" if !-f $path;

8c7f25bc Martin Helmling
return $path;
}

sub get_content {
my ($self, %params) = @_;
my $path = $self->get_filepath(%params);
return "" unless $path;
my $contents = File::Slurp::read_file($path);
return \$contents;
}

sub enabled {
bf980f4c Martin Helmling
return 0 unless $::instance_conf->get_doc_files;
return 0 unless $::lx_office_conf{paths}->{document_path};
return 0 unless -d $::lx_office_conf{paths}->{document_path};
8c7f25bc Martin Helmling
return 1;
}

cff4d333 Martin Helmling
sub sync_from_backend {
378828e9 Tamino Steinert
die "Not implemented";
cff4d333 Martin Helmling
}
8c7f25bc Martin Helmling
#
# internals
#

sub _filesystem_path {
my ($self, $dbfile, $version) = @_;

bf980f4c Martin Helmling
die "No files backend enabled" unless $::instance_conf->get_doc_files || $::lx_office_conf{paths}->{document_path};
8c7f25bc Martin Helmling
ee33f8a4 Tamino Steinert
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;
}

8c7f25bc Martin Helmling
# use filesystem with depth 3
my $iddir = sprintf("%04d", $dbfile->id % 1000);
bf980f4c Martin Helmling
my $path = File::Spec->catdir($::lx_office_conf{paths}->{document_path}, $::auth->client->{id}, $iddir, $dbfile->id);
8c7f25bc Martin Helmling
if (!-d $path) {
File::Path::make_path($path, { chmod => 0770 });
}
return File::Spec->catdir($path, $dbfile->id . '_' . $version);
}

1;

__END__

=pod

=encoding utf8

=head1 NAME

SL::File::Backend::Filesystem - Filesystem class for file storage backend

=head1 SYNOPSIS

See the synopsis of L<SL::File::Backend>.

=head1 OVERVIEW

This specific storage backend use a Filesystem which is only accessed by this interface.
This is the big difference to the Webdav backend where the files can be accessed without the control of that backend.
This backend use the database id of the SL::DB::File object as filename. The filesystem has up to 1000 subdirectories
to store the files not to flat in the filesystem. In this Subdirectories for each file an additional subdirectory exists
for the versions of this file.

The Versioning is done via a Versionnumber which is incremented by one for each version.
So the Version 2 of the file with the database id 4 is stored as path {root}/0004/4/4_2.


=head1 METHODS

See methods of L<SL::File::Backend>.

=head1 SEE ALSO

L<SL::File::Backend>

=head1 AUTHOR

Martin Helmling E<lt>martin.helmling@opendynamic.deE<gt>

=cut