Projekt

Allgemein

Profil

Herunterladen (10,2 KB) Statistiken
| Zweig: | Markierung: | Revision:
0e9f27e4 Martin Helmling
package SL::File::Backend::Webdav;

use strict;

use parent qw(SL::File::Backend);
use SL::DB::File;

011e7aeb Bernd Bleßmann
use SL::System::Process;
0e9f27e4 Martin Helmling
use File::Copy;
use File::Slurp;
use File::Basename;
use File::Path qw(make_path);
use File::MimeInfo::Magic;
30a815e3 Bernd Bleßmann
use File::stat;
0e9f27e4 Martin Helmling
#
# public methods
#

sub delete {
my ($self, %params) = @_;
$main::lxdebug->message(LXDebug->DEBUG2(), "del in backend " . $self . " file " . $params{dbfile});
$main::lxdebug->message(LXDebug->DEBUG2(), "file id=" . $params{dbfile}->id * 1);
return 0 unless $params{dbfile};
my ($file_path, undef, undef) = $self->webdav_path($params{dbfile});
unlink($file_path);
return 1;
}

sub rename {
my ($self, %params) = @_;
return 0 unless $params{dbfile};
my (undef, $oldwebdavname) = split(/:/, $params{dbfile}->location, 2);
my ($tofile, $basepath, $basename) = $self->webdav_path($params{dbfile});
my $fromfile = File::Spec->catfile($basepath, $oldwebdavname);
$main::lxdebug->message(LXDebug->DEBUG2(), "renamefrom=" . $fromfile . " to=" . $tofile);
move($fromfile, $tofile);
}

sub save {
my ($self, %params) = @_;
die 'dbfile not exists' unless $params{dbfile};
$main::lxdebug->message(LXDebug->DEBUG2(), "in backend " . $self . " file " . $params{dbfile});
$main::lxdebug->message(LXDebug->DEBUG2(), "file id=" . $params{dbfile}->id);
my $dbfile = $params{dbfile};
die 'no file contents' unless $params{file_path} || $params{file_contents};

if ($params{dbfile}->id * 1 == 0) {

# new element: need id for file
$params{dbfile}->save;
}
my ($tofile, undef, $basename) = $self->webdav_path($params{dbfile});
if ($params{file_path} && -f $params{file_path}) {
copy($params{file_path}, $tofile);
}
elsif ($params{file_contents}) {
open(OUT, "> " . $tofile);
print OUT $params{file_contents};
close(OUT);
}
return 1;
}

sub get_version_count {
my ($self, %params) = @_;
die "no dbfile" unless $params{dbfile};
## TODO
return 1;
}

sub get_mtime {
my ($self, %params) = @_;
die "no dbfile" unless $params{dbfile};
$main::lxdebug->message(LXDebug->DEBUG2(), "version=" .$params{version});
my ($path, undef, undef) = $self->webdav_path($params{dbfile});
90f0e0b4 Jan Büren
die "No file found in Backend: " . $path unless -f $path;
30a815e3 Bernd Bleßmann
my $dt = DateTime->from_epoch(epoch => stat($path)->mtime, time_zone => $::locale->get_local_time_zone()->name)->clone();
0e9f27e4 Martin Helmling
$main::lxdebug->message(LXDebug->DEBUG2(), "dt=" .$dt);
return $dt;
}

sub get_filepath {
my ($self, %params) = @_;
die "no dbfile" unless $params{dbfile};
my ($path, undef, undef) = $self->webdav_path($params{dbfile});
90f0e0b4 Jan Büren
die "No file found in Backend: " . $path unless -f $path;
0e9f27e4 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 sync_from_backend {
my ($self, %params) = @_;
return unless $params{file_type};

$self->sync_all_locations(%params);

}

sub enabled {
8fa22ab8 Jan Büren
return $::instance_conf->get_doc_webdav;
0e9f27e4 Martin Helmling
}

#
# internals
#

my %type_to_path = (
7202756a Bernd Bleßmann
sales_quotation => 'angebote',
sales_order => 'bestellungen',
request_quotation => 'anfragen',
purchase_order => 'lieferantenbestellungen',
sales_delivery_order => 'verkaufslieferscheine',
purchase_delivery_order => 'einkaufslieferscheine',
credit_note => 'gutschriften',
invoice => 'rechnungen',
3f9da67b Bernd Bleßmann
invoice_for_advance_payment => 'rechnungen',
7202756a Bernd Bleßmann
final_invoice => 'rechnungen',
purchase_invoice => 'einkaufsrechnungen',
part => 'waren',
service => 'dienstleistungen',
assembly => 'erzeugnisse',
letter => 'briefe',
general_ledger => 'dialogbuchungen',
gl_transaction => 'dialogbuchungen',
accounts_payable => 'kreditorenbuchungen',
shop_image => 'shopbilder',
customer => 'kunden',
vendor => 'lieferanten',
0e9f27e4 Martin Helmling
);

my %type_to_model = (
7202756a Bernd Bleßmann
sales_quotation => 'Order',
sales_order => 'Order',
request_quotation => 'Order',
purchase_order => 'Order',
sales_delivery_order => 'DeliveryOrder',
purchase_delivery_order => 'DeliveryOrder',
credit_note => 'Invoice',
invoice => 'Invoice',
3f9da67b Bernd Bleßmann
invoice_for_advance_payment => 'Invoice',
7202756a Bernd Bleßmann
final_invoice => 'Invoice',
purchase_invoice => 'PurchaseInvoice',
part => 'Part',
service => 'Part',
assembly => 'Part',
letter => 'Letter',
general_ledger => 'GLTransaction',
gl_transaction => 'GLTransaction',
accounts_payable => 'GLTransaction',
shop_image => 'Part',
customer => 'Customer',
vendor => 'Vendor',
0e9f27e4 Martin Helmling
);

my %model_to_number = (
Order => 'ordnumber',
DeliveryOrder => 'ordnumber',
Invoice => 'invnumber',
PurchaseInvoice => 'invnumber',
Part => 'partnumber',
Letter => 'letternumber',
31378f48 Werner Hahn
GLTransaction => 'reference',
ShopImage => 'partnumber',
01e8c002 Werner Hahn
Customer => 'customernumber',
a258467b Werner Hahn
Vendor => 'vendornumber',
0e9f27e4 Martin Helmling
);

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

#die "No webdav backend enabled" unless $::instance_conf->get_webdav;

my $type = $type_to_path{ $dbfile->object_type };

die "Unknown type" unless $type;

my $number = $dbfile->backend_data;
if ($number eq '') {
$number = $self->_get_number_from_model($dbfile);
$dbfile->backend_data($number);
$dbfile->save;
}
$main::lxdebug->message(LXDebug->DEBUG2(), "file_name=" . $dbfile->file_name ." number=".$number);

630c1ae7 Jan Büren
my @fileparts = split(/_/, $dbfile->file_name);
my $number_ext = pop @fileparts;
my ($maynumber, $ext) = split(/\./, $number_ext, 2);
push @fileparts, $maynumber if $maynumber ne $number;

my $basename = join('_', @fileparts);

0e9f27e4 Martin Helmling
my $path = File::Spec->catdir($self->get_rootdir, "webdav", $::auth->client->{id}, $type, $number);
if (!-d $path) {
File::Path::make_path($path, { chmod => 0770 });
}
630c1ae7 Jan Büren
my $fname = $basename . '_' . $number . '_' . $dbfile->itime->strftime('%Y%m%d_%H%M%S');
0e9f27e4 Martin Helmling
$fname .= '.' . $ext if $ext;

$main::lxdebug->message(LXDebug->DEBUG2(), "webdav path=" . $path . " filename=" . $fname);

return (File::Spec->catfile($path, $fname), $path, $fname);
}

011e7aeb Bernd Bleßmann
sub get_rootdir { SL::System::Process::exe_dir() }
0e9f27e4 Martin Helmling
sub _get_number_from_model {
my ($self, $dbfile) = @_;

my $class = 'SL::DB::' . $type_to_model{ $dbfile->object_type };
eval "require $class";
my $obj = $class->new(id => $dbfile->object_id)->load;
die 'no object found' unless $obj;
my $numberattr = $model_to_number{ $type_to_model{ $dbfile->object_type } };
return $obj->$numberattr;
}

#
# TODO not fully imlemented and tested
#
sub sync_all_locations {
my ($self, %params) = @_;

my %dateparms = (dateformat => 'yyyymmdd');

foreach my $type (keys %type_to_path) {

my @query = (
file_type => $params{file_type},
object_type => $type
);
my @oldfiles = @{ SL::DB::Manager::File->get_all(
query => [
file_type => $params{file_type},
object_type => $type
]
)
};

my $path = File::Spec->catdir($self->get_rootdir, "webdav", $::auth->client->{id},$type_to_path{$type});

if (opendir my $dir, $path) {
foreach my $file (sort { lc $a cmp lc $b }
map { decode("UTF-8", $_) } readdir $dir)
{
next if (($file eq '.') || ($file eq '..'));

my $fname = $file;
$fname =~ s|.*/||;

my ($filename, $number, $date, $time_ext) = split(/_/, $fname);
my ($time, $ext) = split(/\./, $time_ext, 2);

$time = substr($time, 0, 2) . ':' . substr($time, 2, 2) . ':' . substr($time, 4, 2);

#my @found = grep { $_->backend_data eq $fname } @oldfiles;
#if (scalar(@found) > 0) {
# @oldfiles = grep { $_ != @found[0] } @oldfiles;
#}
#else {
my $dbfile = SL::DB::File->new();
my $class = 'SL::DB::Manager::' . $type_to_model{$type};
my $obj =
$class->find_by(
$model_to_number{ $type_to_model{$type} } => $number);
if ($obj) {

my $mime_type = File::MimeInfo::Magic::magic(File::Spec->catfile($path, $fname));
if (!$mime_type) {
# if filename has the suffix "pdf", but is really no pdf set mimetype for no suffix
$mime_type = File::MimeInfo::Magic::mimetype($fname);
$mime_type = 'application/octet-stream' if $mime_type eq 'application/pdf' || !$mime_type;
}

$dbfile->assign_attributes(
object_id => $obj->id,
object_type => $type,
source => $params{file_type} eq 'document' ? 'created' : 'uploaded',
file_type => $params{file_type},
file_name => $filename . '_' . $number . '_' . $ext,
mime_type => $mime_type,
itime => $::locale->parse_date_to_object($date . ' ' . $time, %dateparms),
);
$dbfile->save;
}
#}

closedir $dir;
}
}
}
}

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.


=head1 METHODS

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

=head1 SEE ALSO

L<SL::File::Backend>

=head1 TODO

The synchronization must be tested and a periodical task is needed to synchronize in some time periods.

=head1 AUTHOR

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

=cut