313c9ff31ed119a8287a196d03c1d7b631a77de5
[kivitendo-erp.git] / SL / Webdav / File.pm
1 package SL::Webdav::File;
2
3 use strict;
4 use parent qw(Rose::Object);
5
6 use File::Spec;
7 use File::Copy ();
8 use Carp;
9
10 use Rose::Object::MakeMethods::Generic (
11   scalar => [ qw(webdav filename loaded) ],
12   array  => [
13     qw(objects),
14     add_objects => { interface => 'push', hash_key => 'objects' },
15   ],
16 );
17
18 sub versions {
19   $_[0]->load unless $_[0]->loaded;
20   my $cmp = $_[0]->webdav->version_scheme->cmp;
21   sort { $cmp->($a, $b) } $_[0]->objects;
22 }
23
24 sub latest_version {
25   ($_[0]->versions)[-1]
26 }
27
28 sub load {
29   my ($self) = @_;
30   my @objects = $self->webdav->get_all_objects;
31   my $ref = SL::Webdav::Object->new(filename => $self->filename, webdav => $self->webdav);
32   my ($ref_basename, undef, $ref_extension) = $ref->parse_filename;
33
34   $self->objects(grep { $_->basename eq $ref_basename && $_->extension eq $ref_extension } @objects);
35   $self->loaded(1);
36 }
37
38 sub store {
39   my ($self, %params) = @_;
40
41   croak 'Invalid call. Only data or file can be set' if ($params{data} && $params{file});
42
43   $self->load unless $self->loaded;
44
45   my $last = $self->latest_version;
46   my $object;
47
48   if (!$last) {
49     my ($basename, undef, $extension) = SL::Webdav::Object->new(filename => $self->filename, webdav => $self->webdav)->parse_filename;
50     my $new_version  = $self->webdav->version_scheme->first_version;
51     my $sep          = $self->webdav->version_scheme->separator;
52     my $new_filename = $basename . $sep . $new_version . "." . $extension;
53     $object = SL::Webdav::Object->new(filename => $new_filename, webdav => $self->webdav);
54
55     $self->add_objects($object);
56   } else {
57     if (!$self->webdav->version_scheme->keep_last_version($last)) {
58       $params{new_version} = 1;
59     }
60
61     if ($params{new_version}) {
62       my $new_version  = $self->webdav->version_scheme->next_version($last);
63       my $sep          = $self->webdav->version_scheme->separator;
64       my $new_filename = $last->basename . $sep . $new_version . "." . $last->extension;
65       $object = SL::Webdav::Object->new(filename => $new_filename, webdav => $self->webdav);
66
67       $self->add_objects($object);
68     } else {
69       $object = $last;
70     }
71   }
72
73   if ($params{file}) {
74     croak 'No valid file' unless -f $params{file};
75     File::Copy::copy($params{file}, $object->full_filedescriptor) or croak "Copy failed from $params{file} to @{[ $object->filename ]}: $!";
76   } else {
77
78     open my $fh, '>:raw', $object->full_filedescriptor or die "could not open " . $object->filename . ": $!";
79
80     $fh->print(${ $params{data} });
81
82     close $fh;
83   }
84
85
86   return $object;
87 }
88
89 1;
90
91 __END__
92
93 =encoding utf-8
94
95 =head1 NAME
96
97 SL::Webdav::File - Webdav file manipulation
98
99 =head1 SYNOPSIS
100
101   use SL::Webdav::File;
102
103   my $webdav_file = SL::Webdav::File->new(
104     webdav   => $webdav,  # SL::Webdav instance
105     filename => 'technical_drawing_AB28375.pdf',
106   );
107
108   # get existing versioned files
109   my @webdav_objects = $webdav_file->versions;
110
111   # store new version
112   my $data = SL::Helper::CreatePDF->create_pdf(...);
113   my $webdav_object = $webdav_file->store(data => \$data);
114
115   # use file instead of data
116   my $webdav_object = $webdav_file->store(file => $path_to_file);
117
118   # force new version
119   my $webdav_object = $webdav_file->store(data => \$data, new_version => 1);
120
121 =head1 DESCRIPTION
122
123 A file in this context is the collection of all versions of a single file saved
124 into the webdav. This module provides methods to access and manipulate these
125 objects.
126
127 =head1 FUNCTIONS
128
129 =over 4
130
131 =item C<versions>
132
133 Will return all L<SL::Webdav::Object>s found in this file, sorted by version
134 according to the version scheme used.
135
136 =item C<latest_version>
137
138 Returns only the latest version object.
139
140 =item C<load>
141
142 Loads objects from disk.
143
144 =item C<store PARAMS>
145
146 Store a new version on disk. If C<data> is present, it is expected to contain a
147 reference to the data to be written in raw encoding.
148
149 If C<file> is a valid filename then it will be copied.
150
151 C<file> and C<data> are exclusive.
152
153 If param C<new_version> is set, force a new version, even if the versioning
154 scheme would keep the old one.
155
156 =back
157
158 =head1 SEE ALSO
159
160 L<SL::Webdav>, L<SL::Webdav::Object>
161
162 =head1 BUGS
163
164 None yet :)
165
166 =head1 AUTHOR
167
168 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
169
170 =cut