Projekt

Allgemein

Profil

Herunterladen (5,48 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;
4412b603 Tamino Steinert
use SL::DB::FileVersion;
46d48c74 Jan Büren
bef56e29 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);
46d48c74 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};
bef56e29 Tamino Steinert
my @versions = @{$params{dbfile}->file_versions_sorted};

my @versions_to_delete;
if ($params{last}) {
my $last = pop @versions;
@versions_to_delete = ($last);
} elsif ($params{all_but_notlast}) {
pop @versions; # remove last
@versions_to_delete = @versions;
} elsif ($params{version}) {
my $version = first {$_->version == $params{version}} @versions
or confess "Version not found.";
@versions_to_delete = ($version);
8c7f25bc Martin Helmling
} else {
bef56e29 Tamino Steinert
@versions_to_delete = @versions;
8c7f25bc Martin Helmling
}

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

return 1;
8c7f25bc Martin Helmling
}

sub save {
my ($self, %params) = @_;
c17045ff 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;
}

bef56e29 Tamino Steinert
my @versions = @{$dbfile->file_versions_sorted};
my $new_version_number = scalar @versions ? $versions[-1]->version + 1 : 1;
8c7f25bc Martin Helmling
bef56e29 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);
c17045ff Jan Büren
} elsif ($params{file_contents}) {
8c7f25bc Martin Helmling
open(OUT, "> " . $tofile);
print OUT $params{file_contents};
close(OUT);
}
4412b603 Tamino Steinert
# save file version
46d48c74 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(
4412b603 Tamino Steinert
file_id => $dbfile->id,
bef56e29 Tamino Steinert
version => $new_version_number,
4412b603 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};
bef56e29 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) = @_;
bef56e29 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 {
bef56e29 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
# use filesystem with depth 3
bef56e29 Tamino Steinert
$version ||= $dbfile->file_versions_sorted->[-1]->version;
confess "Version is required." unless $version;
8c7f25bc Martin Helmling
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