kivitendo/SL/Webdav.pm @ 79b7fc43
dc6d8231 | Sven Schöling | package SL::Webdav;
|
|
use strict;
|
|||
use parent qw(Rose::Object);
|
|||
use Encode qw(decode);
|
|||
use File::Spec;
|
|||
use SL::Common;
|
|||
use SL::Webdav::File;
|
|||
use SL::Webdav::Object;
|
|||
use SL::Webdav::VersionScheme::Serial;
|
|||
use SL::Webdav::VersionScheme::Timestamp;
|
|||
use Rose::Object::MakeMethods::Generic (
|
|||
scalar => [ qw(type number) ],
|
|||
'scalar --get_set_init' => [ qw(version_scheme) ],
|
|||
);
|
|||
my %type_to_path = (
|
|||
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',
|
|||
purchase_invoice => 'einkaufsrechnungen',
|
|||
part => 'waren',
|
|||
service => 'dienstleistungen',
|
|||
assembly => 'erzeugnisse',
|
|||
);
|
|||
sub get_all_files {
|
|||
my ($self) = @_;
|
|||
my @objects = $self->get_all_objects;
|
|||
my %files_by_name;
|
|||
for my $obj (@objects) {
|
|||
my $filename = join '.', grep $_, $obj->basename, $obj->extension;
|
|||
my $file = $files_by_name{$filename} ||= SL::Webdav::File->new(filename => $filename, webdav => $self, loaded => 1);
|
|||
$file->add_objects($obj);
|
|||
}
|
|||
return values %files_by_name;
|
|||
}
|
|||
sub get_all_objects {
|
|||
my ($self) = @_;
|
|||
my $path = $self->webdav_path;
|
|||
my @objects;
|
|||
my $base_path = $ENV{'SCRIPT_NAME'};
|
|||
$base_path =~ s|[^/]+$||;
|
|||
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|.*/||;
|
|||
push @objects, SL::Webdav::Object->new(filename => $fname, webdav => $self);
|
|||
}
|
|||
closedir $dir;
|
|||
return @objects;
|
|||
}
|
|||
}
|
|||
sub get_all_latest {
|
|||
my ($self) = @_;
|
|||
my @files = $self->get_all_files;
|
|||
map { ($_->versions)[-1] } @files;
|
|||
}
|
|||
sub _sanitized_number {
|
|||
my $number = $_[0]->number;
|
|||
$number =~ s|[/\\]|_|g;
|
|||
$number;
|
|||
}
|
|||
sub webdav_path {
|
|||
my ($self) = @_;
|
|||
die "No client set in \$::auth" unless $::auth->client;
|
|||
die "Need number" unless $self->number;
|
|||
my $type = $type_to_path{$self->type};
|
|||
die "Unknown type" unless $type;
|
|||
my $path = File::Spec->catdir("webdav", $::auth->client->{id}, $type, $self->_sanitized_number);
|
|||
if (!-d $path) {
|
|||
Common::mkdir_with_parents($path);
|
|||
}
|
|||
return $path;
|
|||
}
|
|||
sub init_version_scheme {
|
|||
SL::Webdav::VersionScheme::Timestamp->new;
|
|||
}
|
|||
1;
|
|||
__END__
|
|||
=encoding utf-8
|
|||
=head1 NAME
|
|||
SL::Webdav - Webdav manipulation
|
|||
=head1 SYNOPSIS
|
|||
# get list of all documents for this record
|
|||
use SL::Webdav;
|
|||
my $webdav = SL::Webdav->new(
|
|||
type => 'part',
|
|||
number => $number,
|
|||
);
|
|||
# gives you SL::Webdav::File instances
|
|||
my $webdav_files = $webdav->get_all_files;
|
|||
# gives you the objects instead
|
|||
my $webdav_objects = $webdav->get_all_objects;
|
|||
# gives you only the latest objects
|
|||
my $webdav_objects = $webdav->get_all_latest;
|
|||
# physical path to this dir
|
|||
my $path = $webdav->webdav_path;
|
|||
=head1 DESCRIPTION
|
|||
This module is a wrapper around the webdav storage mechanism with some simple
|
|||
document management functionality.
|
|||
This is not a replacement for real document management, mostly because the
|
|||
underlying webdav storage ist not fully under our control. It's common practice
|
|||
to allow people direct samba access to the webdav, so all versioning
|
|||
information need to be encoded into the filename of a file, and nonsensical
|
|||
filenames must not break assumptions.
|
|||
This module is intended to be used if you need to scan the folder for
|
|||
previously saved files and need to build a list to display for it.
|
|||
If you need to manipulate the versions of a file, see L<SL::Webdav::File>
|
|||
If you need to access a file directly for download or metadata, see L<SL::Webdav::Object>
|
|||
=head1 FUNCTIONS
|
|||
=over 4
|
|||
=item C<get_all_objects>
|
|||
Returns all L<SL::Webdav::Objects> found.
|
|||
=item C<get_all_files>
|
|||
Returns all objects sorted into L<SL::Webdav::File>s.
|
|||
=item C<get_all_latest>
|
|||
Returns only the latest object of each L<SL::Webdav::File> found.
|
|||
=item C<webdav_path>
|
|||
Returns the physical path to this webdav object.
|
|||
=back
|
|||
=head1 VERSIONING SCHEME
|
|||
You may register a versioning scheme object to hangdle versioning. It is
|
|||
expected to implement the following methods:
|
|||
=over 4
|
|||
=item C<separator>
|
|||
Must return a string that will be used to separate basename and version part of
|
|||
filenames in generating and parsing.
|
|||
=item C<extract_regexp>
|
|||
Must return a regexp that will match a versioning string at the end of a
|
|||
filename after the extension has been stripped off. It will be surrounded by
|
|||
captures.
|
|||
=item C<cmp>
|
|||
Must return a comparison function that will be invoked with two
|
|||
L<SL::Webdav::Object> instances.
|
|||
=item C<first_version>
|
|||
Must return a string representing the version of the first of a series of objects.
|
|||
May return undef.
|
|||
=item C<next_version>
|
|||
Will be called with the latest L<SL::Webdav::Object> and must return a new version string.
|
|||
=item C<keep_last_version>
|
|||
Will be called with the latest L<SL::Webdav::Object>. Truish return value will
|
|||
cause the latest object to be overwritten instead of creating a new version.
|
|||
=back
|
|||
=head1 BUGS AND CAVEATS
|
|||
=over 4
|
|||
=item *
|
|||
File operations are inconsistently L<File::Spec>ed.
|
|||
=back
|
|||
=head1 SEE ALSO
|
|||
L<SL::Webdav::File>, L<SL::Webdav::Object>
|
|||
=head1 AUTHOR
|
|||
Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
|
|||
=cut
|