Revision 2bb452ee
Von Martin Helmling mh@waldpark.octosoft.eu vor fast 8 Jahren hinzugefügt
SL/Controller/ClientConfig.pm | ||
---|---|---|
212 | 212 |
sub edit_form { |
213 | 213 |
my ($self) = @_; |
214 | 214 |
|
215 |
$::request->layout->use_javascript("${_}.js") for qw(jquery.selectboxes jquery.multiselect2side); |
|
215 |
$::request->layout->use_javascript("${_}.js") for qw(jquery.selectboxes jquery.multiselect2side kivi.File);
|
|
216 | 216 |
|
217 | 217 |
$self->render('client_config/form', title => t8('Client Configuration'), |
218 | 218 |
make_chart_title => sub { $_[0]->accno . '--' . $_[0]->description }, |
SL/DB/File.pm | ||
---|---|---|
1 |
# This file has been auto-generated only because it didn't exist. |
|
2 |
# Feel free to modify it at will; it will not be overwritten automatically. |
|
3 |
|
|
4 |
package SL::DB::File; |
|
5 |
|
|
6 |
use strict; |
|
7 |
|
|
8 |
use SL::DB::MetaSetup::File; |
|
9 |
use SL::DB::Manager::File; |
|
10 |
|
|
11 |
__PACKAGE__->meta->initialize; |
|
12 |
|
|
13 |
|
|
14 |
1; |
|
15 |
__END__ |
|
16 |
|
|
17 |
=pod |
|
18 |
|
|
19 |
=encoding utf8 |
|
20 |
|
|
21 |
=head1 NAME |
|
22 |
|
|
23 |
SL::DB::File - Databaseclass for File |
|
24 |
|
|
25 |
=head1 SYNOPSIS |
|
26 |
|
|
27 |
use SL::DB::File; |
|
28 |
|
|
29 |
# synopsis... |
|
30 |
|
|
31 |
=head1 DESCRIPTION |
|
32 |
|
|
33 |
# longer description. |
|
34 |
|
|
35 |
|
|
36 |
=head1 INTERFACE |
|
37 |
|
|
38 |
|
|
39 |
=head1 DEPENDENCIES |
|
40 |
|
|
41 |
|
|
42 |
=head1 SEE ALSO |
|
43 |
|
|
44 |
=head1 AUTHOR |
|
45 |
|
|
46 |
Werner Hahn E<lt>wh@futureworldsearch.netE<gt> |
|
47 |
|
|
48 |
=cut |
SL/DB/Helper/ALL.pm | ||
---|---|---|
51 | 51 |
use SL::DB::EmailJournalAttachment; |
52 | 52 |
use SL::DB::Employee; |
53 | 53 |
use SL::DB::Exchangerate; |
54 |
use SL::DB::File; |
|
54 | 55 |
use SL::DB::Finanzamt; |
55 | 56 |
use SL::DB::FollowUp; |
56 | 57 |
use SL::DB::FollowUpAccess; |
SL/DB/Helper/Mappings.pm | ||
---|---|---|
135 | 135 |
email_journal_attachments => 'EmailJournalAttachment', |
136 | 136 |
employee => 'employee', |
137 | 137 |
exchangerate => 'exchangerate', |
138 |
files => 'file', |
|
138 | 139 |
finanzamt => 'finanzamt', |
139 | 140 |
follow_up_access => 'follow_up_access', |
140 | 141 |
follow_up_links => 'follow_up_link', |
SL/DB/Manager/File.pm | ||
---|---|---|
1 |
# This file has been auto-generated only because it didn't exist. |
|
2 |
# Feel free to modify it at will; it will not be overwritten automatically. |
|
3 |
|
|
4 |
package SL::DB::Manager::File; |
|
5 |
|
|
6 |
use strict; |
|
7 |
|
|
8 |
use parent qw(SL::DB::Helper::Manager); |
|
9 |
use SL::DB::Helper::Sorted; |
|
10 |
|
|
11 |
sub object_class { 'SL::DB::File' } |
|
12 |
|
|
13 |
__PACKAGE__->make_manager_methods; |
|
14 |
|
|
15 |
1; |
SL/DB/MetaSetup/Default.pm | ||
---|---|---|
45 | 45 |
datev_check_on_purchase_invoice => { type => 'boolean', default => 'true' }, |
46 | 46 |
datev_check_on_sales_invoice => { type => 'boolean', default => 'true' }, |
47 | 47 |
disabled_price_sources => { type => 'array' }, |
48 |
doc_database => { type => 'boolean', default => 'false' }, |
|
49 |
doc_delete_printfiles => { type => 'boolean', default => 'false' }, |
|
50 |
doc_files => { type => 'boolean', default => 'false' }, |
|
51 |
doc_files_rootpath => { type => 'text', default => '' }, |
|
52 |
doc_max_filesize => { type => 'integer', default => 1000000 }, |
|
53 |
doc_storage => { type => 'boolean', default => 'false' }, |
|
54 |
doc_storage_for_attachments => { type => 'text', default => 'Filesystem' }, |
|
55 |
doc_storage_for_documents => { type => 'text', default => 'Filesystem' }, |
|
56 |
doc_storage_for_images => { type => 'text', default => 'Filesystem' }, |
|
57 |
doc_webdav => { type => 'boolean', default => 'false' }, |
|
48 | 58 |
dunning_ar => { type => 'integer' }, |
49 | 59 |
dunning_ar_amount_fee => { type => 'integer' }, |
50 | 60 |
dunning_ar_amount_interest => { type => 'integer' }, |
SL/DB/MetaSetup/File.pm | ||
---|---|---|
1 |
# This file has been auto-generated. Do not modify it; it will be overwritten |
|
2 |
# by rose_auto_create_model.pl automatically. |
|
3 |
package SL::DB::File; |
|
4 |
|
|
5 |
use strict; |
|
6 |
|
|
7 |
use parent qw(SL::DB::Object); |
|
8 |
|
|
9 |
__PACKAGE__->meta->table('files'); |
|
10 |
|
|
11 |
__PACKAGE__->meta->columns( |
|
12 |
backend => { type => 'text' }, |
|
13 |
backend_data => { type => 'text' }, |
|
14 |
description => { type => 'text' }, |
|
15 |
file_name => { type => 'text', not_null => 1 }, |
|
16 |
file_type => { type => 'text', not_null => 1 }, |
|
17 |
id => { type => 'serial', not_null => 1 }, |
|
18 |
itime => { type => 'timestamp', default => 'now()' }, |
|
19 |
mime_type => { type => 'text', not_null => 1 }, |
|
20 |
mtime => { type => 'timestamp' }, |
|
21 |
object_id => { type => 'integer', not_null => 1 }, |
|
22 |
object_type => { type => 'text', not_null => 1 }, |
|
23 |
source => { type => 'text', not_null => 1 }, |
|
24 |
title => { type => 'varchar', length => 45 }, |
|
25 |
); |
|
26 |
|
|
27 |
__PACKAGE__->meta->primary_key_columns([ 'id' ]); |
|
28 |
|
|
29 |
__PACKAGE__->meta->allow_inline_column_values(1); |
|
30 |
|
|
31 |
1; |
|
32 |
; |
SL/Dev/File.pm | ||
---|---|---|
1 |
package SL::Dev::File; |
|
2 |
|
|
3 |
use strict; |
|
4 |
use base qw(Exporter); |
|
5 |
our @EXPORT = qw(create_scanned create_uploaded create_created get_all_count get_all get_all_versions delete_all); |
|
6 |
|
|
7 |
use SL::DB::File; |
|
8 |
|
|
9 |
sub create_scanned { |
|
10 |
my (%params) = @_; |
|
11 |
$params{source} = 'scanner1'; |
|
12 |
$params{file_type} = 'document'; |
|
13 |
$params{file_path} = '/var/tmp/'.$params{file_name} if !$params{file_path}; |
|
14 |
open(OUT,"> ".$params{file_path}); |
|
15 |
print OUT $params{file_contents}; |
|
16 |
close(OUT); |
|
17 |
delete $params{file_contents}; |
|
18 |
my $file = _create_file(%params); |
|
19 |
unlink($params{file_path}); |
|
20 |
return $file; |
|
21 |
} |
|
22 |
|
|
23 |
sub create_uploaded { |
|
24 |
my (%params) = @_; |
|
25 |
$params{source} = 'uploaded'; |
|
26 |
$params{file_type} = 'attachment'; |
|
27 |
return _create_file(%params); |
|
28 |
} |
|
29 |
|
|
30 |
sub create_created { |
|
31 |
my (%params) = @_; |
|
32 |
$params{source} = 'created'; |
|
33 |
$params{file_type} = 'document'; |
|
34 |
return _create_file(%params); |
|
35 |
} |
|
36 |
|
|
37 |
sub _create_file { |
|
38 |
my (%params) = @_; |
|
39 |
|
|
40 |
my $fileobj = SL::File->save( |
|
41 |
object_id => 1, |
|
42 |
object_type => 'sales_order', |
|
43 |
mime_type => 'text/plain', |
|
44 |
description => 'Test File', |
|
45 |
file_type => $params{file_type}, |
|
46 |
source => $params{source}, |
|
47 |
file_name => $params{file_name}, |
|
48 |
file_contents => $params{file_contents}, |
|
49 |
file_path => $params{file_path} |
|
50 |
); |
|
51 |
return $fileobj; |
|
52 |
} |
|
53 |
|
|
54 |
sub get_all_count { |
|
55 |
my ($class,%params) = @_; |
|
56 |
$params{object_id} = 1; |
|
57 |
$params{object_type} = 'sales_order'; |
|
58 |
return SL::File->get_all_count(%params); |
|
59 |
} |
|
60 |
|
|
61 |
sub get_all { |
|
62 |
my ($class,%params) = @_; |
|
63 |
$params{object_id} = 1; |
|
64 |
$params{object_type} = 'sales_order'; |
|
65 |
SL::File->get_all(%params); |
|
66 |
} |
|
67 |
|
|
68 |
sub get_all_versions { |
|
69 |
my ($class,%params) = @_; |
|
70 |
$params{object_id} = 1; |
|
71 |
$params{object_type} = 'sales_order'; |
|
72 |
SL::File->get_all_versions(%params); |
|
73 |
} |
|
74 |
|
|
75 |
sub delete_all { |
|
76 |
my ($class,%params) = @_; |
|
77 |
$params{object_id} = 1; |
|
78 |
$params{object_type} = 'sales_order'; |
|
79 |
SL::File->delete_all(%params); |
|
80 |
} |
|
81 |
1; |
|
82 |
|
|
83 |
__END__ |
|
84 |
|
|
85 |
=head1 NAME |
|
86 |
|
|
87 |
SL::Dev::File - create file objects for testing, with minimal defaults |
|
88 |
|
|
89 |
=head1 FUNCTIONS |
|
90 |
|
|
91 |
=head2 C<create_scanned %PARAMS> |
|
92 |
|
|
93 |
=head2 C<create_uploaded %PARAMS> |
|
94 |
|
|
95 |
=head2 C<create_created %PARAMS> |
|
96 |
|
|
97 |
=head2 C<delete_all> |
|
98 |
|
|
99 |
=head1 AUTHOR |
|
100 |
|
|
101 |
Martin Helmling E<lt>martin.helmling@opendynamic.deE<gt> |
|
102 |
|
|
103 |
=cut |
SL/File.pm | ||
---|---|---|
1 |
package SL::File; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use parent qw(Rose::Object); |
|
6 |
|
|
7 |
use Clone qw(clone); |
|
8 |
use SL::File::Backend; |
|
9 |
use SL::File::Object; |
|
10 |
use SL::DB::History; |
|
11 |
use SL::DB::File; |
|
12 |
use SL::Helper::UserPreferences; |
|
13 |
use SL::JSON; |
|
14 |
|
|
15 |
use constant RENAME_OK => 0; |
|
16 |
use constant RENAME_EXISTS => 1; |
|
17 |
use constant RENAME_NOFILE => 2; |
|
18 |
use constant RENAME_SAME => 3; |
|
19 |
use constant RENAME_NEW_VERSION => 4; |
|
20 |
|
|
21 |
sub get { |
|
22 |
my ($self, %params) = @_; |
|
23 |
die 'no id' unless $params{id}; |
|
24 |
my $dbfile = SL::DB::Manager::File->get_first(query => [id => $params{id}]); |
|
25 |
die 'not found' unless $dbfile; |
|
26 |
$main::lxdebug->message(LXDebug->DEBUG2(), "object_id=".$dbfile->object_id." object_type=".$dbfile->object_type." dbfile=".$dbfile); |
|
27 |
SL::File::Object->new(db_file => $dbfile, id => $dbfile->id, loaded => 1); |
|
28 |
} |
|
29 |
|
|
30 |
sub get_version_count { |
|
31 |
my ($self, %params) = @_; |
|
32 |
die "no id or dbfile" unless $params{id} || $params{dbfile}; |
|
33 |
$params{dbfile} = SL::DB::Manager::File->get_first(query => [id => $params{id}]) if !$params{dbfile}; |
|
34 |
die 'not found' unless $params{dbfile}; |
|
35 |
my $backend = $self->_get_backend($params{dbfile}->backend); |
|
36 |
return $backend->get_version_count(%params); |
|
37 |
} |
|
38 |
|
|
39 |
sub get_all { |
|
40 |
my ($self, %params) = @_; |
|
41 |
|
|
42 |
my @files; |
|
43 |
return @files unless $params{object_type}; |
|
44 |
return @files unless defined($params{object_id}); |
|
45 |
|
|
46 |
my @query = ( |
|
47 |
object_id => $params{object_id}, |
|
48 |
object_type => $params{object_type} |
|
49 |
); |
|
50 |
push @query, (file_name => $params{file_name}) if $params{file_name}; |
|
51 |
push @query, (file_type => $params{file_type}) if $params{file_type}; |
|
52 |
push @query, (mime_type => $params{mime_type}) if $params{mime_type}; |
|
53 |
push @query, (source => $params{source}) if $params{source}; |
|
54 |
|
|
55 |
my $sortby = $params{sort_by} || 'itime DESC,file_name ASC'; |
|
56 |
|
|
57 |
@files = @{ SL::DB::Manager::File->get_all(query => [@query], sort_by => $sortby) }; |
|
58 |
map { SL::File::Object->new(db_file => $_, id => $_->id, loaded => 1) } @files; |
|
59 |
} |
|
60 |
|
|
61 |
sub get_all_versions { |
|
62 |
my ($self, %params) = @_; |
|
63 |
my @versionobjs; |
|
64 |
my @fileobjs = $self->get_all(%params); |
|
65 |
if ( $params{dbfile} ) { |
|
66 |
push @fileobjs, SL::File::Object->new(dbfile => $params{db_file}, id => $params{dbfile}->id, loaded => 1); |
|
67 |
} else { |
|
68 |
@fileobjs = $self->get_all(%params); |
|
69 |
} |
|
70 |
foreach my $fileobj (@fileobjs) { |
|
71 |
$main::lxdebug->message(LXDebug->DEBUG2(), "obj=" . $fileobj . " id=" . $fileobj->id." versions=".$fileobj->version_count); |
|
72 |
my $maxversion = $fileobj->version_count; |
|
73 |
push @versionobjs, $fileobj; |
|
74 |
if ($maxversion > 1) { |
|
75 |
for my $version (2..$maxversion) { |
|
76 |
$main::lxdebug->message(LXDebug->DEBUG2(), "clone for version=".($maxversion-$version+1)); |
|
77 |
eval { |
|
78 |
my $clone = clone($fileobj); |
|
79 |
$clone->version($maxversion-$version+1); |
|
80 |
$clone->newest(0); |
|
81 |
$main::lxdebug->message(LXDebug->DEBUG2(), "clone version=".$clone->version." mtime=". $clone->mtime); |
|
82 |
push @versionobjs, $clone; |
|
83 |
1; |
|
84 |
} |
|
85 |
} |
|
86 |
} |
|
87 |
} |
|
88 |
return @versionobjs; |
|
89 |
} |
|
90 |
|
|
91 |
sub get_all_count { |
|
92 |
my ($self, %params) = @_; |
|
93 |
return 0 unless $params{object_type}; |
|
94 |
|
|
95 |
my @query = ( |
|
96 |
object_id => $params{object_id}, |
|
97 |
object_type => $params{object_type} |
|
98 |
); |
|
99 |
push @query, (file_name => $params{file_name}) if $params{file_name}; |
|
100 |
push @query, (file_type => $params{file_type}) if $params{file_type}; |
|
101 |
push @query, (mime_type => $params{mime_type}) if $params{mime_type}; |
|
102 |
push @query, (source => $params{source}) if $params{source}; |
|
103 |
|
|
104 |
my $cnt = SL::DB::Manager::File->get_all_count(query => [@query]); |
|
105 |
return $cnt; |
|
106 |
} |
|
107 |
|
|
108 |
sub delete_all { |
|
109 |
my ($self, %params) = @_; |
|
110 |
return 0 unless defined($params{object_id}) || $params{object_type}; |
|
111 |
my $files = SL::DB::Manager::File->get_all( |
|
112 |
query => [ |
|
113 |
object_id => $params{object_id}, |
|
114 |
object_type => $params{object_type} |
|
115 |
] |
|
116 |
); |
|
117 |
foreach my $file (@{$files}) { |
|
118 |
$params{dbfile} = $file; |
|
119 |
$self->delete(%params); |
|
120 |
} |
|
121 |
} |
|
122 |
|
|
123 |
sub delete { |
|
124 |
my ($self, %params) = @_; |
|
125 |
die "no id or dbfile" unless $params{id} || $params{dbfile}; |
|
126 |
my $rc = SL::DB->client->with_transaction(\&_delete, $self, %params); |
|
127 |
if (!$rc) { |
|
128 |
my $err = SL::DB->client->error; |
|
129 |
die (ref $err?$$err:$err); |
|
130 |
} |
|
131 |
return $rc; |
|
132 |
} |
|
133 |
|
|
134 |
sub _delete { |
|
135 |
my ($self, %params) = @_; |
|
136 |
$params{dbfile} = SL::DB::Manager::File->get_first(query => [id => $params{id}]) if !$params{dbfile}; |
|
137 |
|
|
138 |
my $backend = $self->_get_backend($params{dbfile}->backend); |
|
139 |
if ( $params{dbfile}->file_type eq 'document' && $params{dbfile}->source ne 'created') |
|
140 |
{ |
|
141 |
## must unimport |
|
142 |
my $hist = SL::DB::Manager::History->get_first( |
|
143 |
where => [ |
|
144 |
addition => 'IMPORT', |
|
145 |
trans_id => $params{dbfile}->object_id, |
|
146 |
what_done => $params{dbfile}->id |
|
147 |
] |
|
148 |
); |
|
149 |
|
|
150 |
if ($hist) { |
|
151 |
if (!$main::auth->assert('import_ar | import_ap', 1)) { |
|
152 |
die \'no permission to unimport'; |
|
153 |
} |
|
154 |
my $file = $backend->get_filepath(dbfile => $params{dbfile}); |
|
155 |
$main::lxdebug->message(LXDebug->DEBUG2(), "del file=" . $file . " to=" . $hist->snumbers); |
|
156 |
File::Copy::copy($file, $hist->snumbers) if $file; |
|
157 |
$hist->addition('UNIMPORT'); |
|
158 |
$hist->save; |
|
159 |
} |
|
160 |
} |
|
161 |
if ($backend->delete(%params)) { |
|
162 |
my $do_delete = 0; |
|
163 |
if ( $params{last} || $params{all_but_notlast} ) { |
|
164 |
if ( $backend->get_version_count > 0 ) { |
|
165 |
$params{dbfile}->mtime(DateTime->now_local); |
|
166 |
$params{dbfile}->save; |
|
167 |
} else { |
|
168 |
$do_delete = 1; |
|
169 |
} |
|
170 |
} else { |
|
171 |
$do_delete = 1; |
|
172 |
} |
|
173 |
$params{dbfile}->delete if $do_delete; |
|
174 |
return 1; |
|
175 |
} |
|
176 |
return 0; |
|
177 |
} |
|
178 |
|
|
179 |
sub save { |
|
180 |
my ($self, %params) = @_; |
|
181 |
|
|
182 |
my $obj = SL::DB->client->with_transaction(\&_save, $self, %params); |
|
183 |
if (!$obj) { |
|
184 |
my $err = SL::DB->client->error; |
|
185 |
die (ref $err?$$err:$err); |
|
186 |
} |
|
187 |
return $obj; |
|
188 |
} |
|
189 |
|
|
190 |
sub _save { |
|
191 |
my ($self, %params) = @_; |
|
192 |
my $file = $params{dbfile}; |
|
193 |
my $exists = 0; |
|
194 |
|
|
195 |
if ($params{id}) { |
|
196 |
$file = SL::DB::File->new(id => $params{id})->load; |
|
197 |
die \'dbfile not exists' unless $file; |
|
198 |
} elsif (!$file) { |
|
199 |
$main::lxdebug->message(LXDebug->DEBUG2(), "obj_id=" .$params{object_id}); |
|
200 |
die \'no object type set' unless $params{object_type}; |
|
201 |
die \'no object id set' unless defined($params{object_id}); |
|
202 |
|
|
203 |
$exists = $self->get_all_count(%params); |
|
204 |
die 'filename still exist' if $exists && $params{fail_if_exists}; |
|
205 |
if ($exists) { |
|
206 |
my ($obj1) = $self->get_all(%params); |
|
207 |
$file = $obj1->db_file; |
|
208 |
} else { |
|
209 |
$file = SL::DB::File->new(); |
|
210 |
$file->assign_attributes( |
|
211 |
object_id => $params{object_id}, |
|
212 |
object_type => $params{object_type}, |
|
213 |
source => $params{source}, |
|
214 |
file_type => $params{file_type}, |
|
215 |
file_name => $params{file_name}, |
|
216 |
mime_type => $params{mime_type}, |
|
217 |
title => $params{title}, |
|
218 |
description => $params{description}, |
|
219 |
); |
|
220 |
} |
|
221 |
} else { |
|
222 |
$exists = 1; |
|
223 |
} |
|
224 |
if ($exists) { |
|
225 |
#change attr on existing file |
|
226 |
$file->file_name ($params{file_name}) if $params{file_name}; |
|
227 |
$file->mime_type ($params{mime_type}) if $params{mime_type}; |
|
228 |
$file->title ($params{title}) if $params{title}; |
|
229 |
$file->description($params{description}) if $params{description}; |
|
230 |
} |
|
231 |
if ( !$file->backend ) { |
|
232 |
$file->backend($self->_get_backend_by_file_type($file)); |
|
233 |
# load itime for new file |
|
234 |
$file->save->load; |
|
235 |
} |
|
236 |
$main::lxdebug->message(LXDebug->DEBUG2(), "backend3=" .$file->backend); |
|
237 |
my $backend = $self->_get_backend($file->backend); |
|
238 |
$params{dbfile} = $file; |
|
239 |
$backend->save(%params); |
|
240 |
|
|
241 |
$file->mtime(DateTime->now_local); |
|
242 |
$file->save; |
|
243 |
if ($params{file_type} eq 'document' && $params{source} ne 'created') { |
|
244 |
SL::DB::History->new( |
|
245 |
addition => 'IMPORT', |
|
246 |
trans_id => $params{object_id}, |
|
247 |
snumbers => $params{file_path}, |
|
248 |
employee_id => SL::DB::Manager::Employee->current->id, |
|
249 |
what_done => $params{dbfile}->id |
|
250 |
)->save(); |
|
251 |
} |
|
252 |
return $params{obj} if $params{dbfile} && $params{obj}; |
|
253 |
return SL::File::Object->new(db_file => $file, id => $file->id, loaded => 1); |
|
254 |
} |
|
255 |
|
|
256 |
sub rename { |
|
257 |
my ($self, %params) = @_; |
|
258 |
return RENAME_NOFILE unless $params{id} || $params{dbfile}; |
|
259 |
my $file = $params{dbfile}; |
|
260 |
$file = SL::DB::Manager::File->get_first(query => [id => $params{id}]) if !$file; |
|
261 |
return RENAME_NOFILE unless $file; |
|
262 |
|
|
263 |
$main::lxdebug->message(LXDebug->DEBUG2(), "rename id=" . $file->id . " to=" . $params{to}); |
|
264 |
if ($params{to}) { |
|
265 |
return RENAME_SAME if $params{to} eq $file->file_name; |
|
266 |
return RENAME_EXISTS if $self->get_all_count( object_id => $file->object_id, |
|
267 |
object_type => $file->object_type, |
|
268 |
mime_type => $file->mime_type, |
|
269 |
source => $file->source, |
|
270 |
file_type => $file->file_type, |
|
271 |
file_name => $params{to} |
|
272 |
) > 0; |
|
273 |
|
|
274 |
my $backend = $self->_get_backend($file->backend); |
|
275 |
$backend->rename(dbfile => $file) if $backend; |
|
276 |
$file->file_name($params{to}); |
|
277 |
$file->save; |
|
278 |
} |
|
279 |
return RENAME_OK; |
|
280 |
} |
|
281 |
|
|
282 |
sub get_backend_class { |
|
283 |
my ($self, $backendname) = @_; |
|
284 |
die "no backend name set" unless $backendname; |
|
285 |
$self->_get_backend($backendname); |
|
286 |
} |
|
287 |
|
|
288 |
sub get_other_sources { |
|
289 |
my ($self) = @_; |
|
290 |
my $pref = SL::Helper::UserPreferences->new(namespace => 'file_sources'); |
|
291 |
$pref->login("#default#"); |
|
292 |
my @sources; |
|
293 |
foreach my $tuple (@{ $pref->get_all() }) { |
|
294 |
my %lkeys = %{ SL::JSON::from_json($tuple->{value}) }; |
|
295 |
my $source = { |
|
296 |
'name' => $tuple->{key}, |
|
297 |
'description' => $lkeys{desc}, |
|
298 |
'directory' => $lkeys{dir} |
|
299 |
}; |
|
300 |
push @sources, $source; |
|
301 |
} |
|
302 |
return @sources; |
|
303 |
} |
|
304 |
|
|
305 |
sub sync_from_backend { |
|
306 |
my ($self, %params) = @_; |
|
307 |
return unless $params{file_type}; |
|
308 |
my $file = SL::DB::File->new; |
|
309 |
$file->file_type($params{file_type}); |
|
310 |
my $backend = $self->_get_backend(dbfile => $file->backend); |
|
311 |
return unless $backend; |
|
312 |
$backend->sync_from_backend(%params); |
|
313 |
} |
|
314 |
|
|
315 |
# |
|
316 |
# internal |
|
317 |
# |
|
318 |
sub _get_backend { |
|
319 |
my ($self, $backend_name) = @_; |
|
320 |
my $class = 'SL::File::Backend::' . $backend_name; |
|
321 |
my $obj = undef; |
|
322 |
eval { |
|
323 |
eval "require $class"; |
|
324 |
$obj = $class->new; |
|
325 |
die \'backend not enabled' unless $obj->enabled; |
|
326 |
1; |
|
327 |
} or do { |
|
328 |
die \'backend class not found'; |
|
329 |
}; |
|
330 |
return $obj; |
|
331 |
} |
|
332 |
|
|
333 |
sub _get_backend_by_file_type { |
|
334 |
my ($self, $dbfile) = @_; |
|
335 |
|
|
336 |
$main::lxdebug->message(LXDebug->DEBUG2(), "_get_backend_by_file_type=" .$dbfile." type=".$dbfile->file_type); |
|
337 |
return "Filesystem" unless $dbfile; |
|
338 |
return $::instance_conf->get_doc_storage_for_documents if $dbfile->file_type eq 'document'; |
|
339 |
return $::instance_conf->get_doc_storage_for_attachments if $dbfile->file_type eq 'attachment'; |
|
340 |
return $::instance_conf->get_doc_storage_for_images if $dbfile->file_type eq 'image'; |
|
341 |
return "Filesystem"; |
|
342 |
} |
|
343 |
|
|
344 |
1; |
|
345 |
|
|
346 |
__END__ |
|
347 |
|
|
348 |
=pod |
|
349 |
|
|
350 |
=encoding utf8 |
|
351 |
|
|
352 |
=head1 NAME |
|
353 |
|
|
354 |
SL::File - The intermediate Layer for handling files |
|
355 |
|
|
356 |
=head1 SYNOPSIS |
|
357 |
|
|
358 |
# In a controller or helper ( see SL::Controller::File or SL::Helper::File ) |
|
359 |
# you can create, remove, delete etc. a file in a backend independant way |
|
360 |
|
|
361 |
my $file = SL::File->save( |
|
362 |
object_id => $self->object_id, |
|
363 |
object_type => $self->object_type, |
|
364 |
mime_type => 'application/pdf', |
|
365 |
file_type => 'documents', |
|
366 |
file_contents => 'this is no pdf'); |
|
367 |
|
|
368 |
my $file1 = SL::File->get(id => $id); |
|
369 |
SL::File->delete(id => $id); |
|
370 |
SL::File->delete(dbfile => $file1); |
|
371 |
SL::File->delete_all(object_id => $object_id, |
|
372 |
object_type => $object_type, |
|
373 |
file_type => $filetype # may be optional |
|
374 |
); |
|
375 |
SL::File->rename(id => $id,to => $newname); |
|
376 |
my $files1 = SL::File->get_all(object_id => $object_id, |
|
377 |
object_type => $object_type, |
|
378 |
file_type => 'images', # may be optional |
|
379 |
source => 'uploaded' # may be optional |
|
380 |
); |
|
381 |
|
|
382 |
# Alternativelly some operation can be done with the filemangement object wrapper |
|
383 |
# and additional oparations see L<SL::File::Object> |
|
384 |
|
|
385 |
=head1 OVERVIEW |
|
386 |
|
|
387 |
The Filemanagemt can handle files in a storage independant way. Internal the File |
|
388 |
use the configured storage backend for the type of file. |
|
389 |
These backends must be configured in L<SL::Controller::ClientConfig> or an extra database table. |
|
390 |
|
|
391 |
There are three types of files: |
|
392 |
|
|
393 |
=over 2 |
|
394 |
|
|
395 |
=item - documents, |
|
396 |
|
|
397 |
which can be generated files (for sales), scanned files or uploaded files (for purchase) for an ERP-object. |
|
398 |
They can exist in different versions. The versioning is handled implicit. All versions of a file may be |
|
399 |
deleted by the user if she/he is allowed to do this. |
|
400 |
|
|
401 |
=item - attachments, |
|
402 |
|
|
403 |
which have additional information for an ERP-objects. They are uploadable. If a filename still exists |
|
404 |
on a ERP-Object the new uploaded file is a new version of this or it must be renamed by user. |
|
405 |
|
|
406 |
There are generic attachments for a specific document group (like sales_invoices). This attachments can be |
|
407 |
combinide/merged with the document-file in the time of printing. |
|
408 |
Today only PDF-Attachmnets can be merged with the generated document-PDF. |
|
409 |
|
|
410 |
=item - images, |
|
411 |
|
|
412 |
they are like attachments, but they may be have thumbnails for displaying. |
|
413 |
So the must have an image format like png,jpg. The versioning is like attachments |
|
414 |
|
|
415 |
=back |
|
416 |
|
|
417 |
For each type of files the backend can configured in L<SL::Controller::ClientConfig>. |
|
418 |
|
|
419 |
The files have also the parameter C<Source>: |
|
420 |
|
|
421 |
=over 2 |
|
422 |
|
|
423 |
=item - created, generated by LaTeX |
|
424 |
|
|
425 |
=item - uploaded |
|
426 |
|
|
427 |
=item - scanner, import from scanner |
|
428 |
|
|
429 |
( or scanner1, scanner2 if there are different scanner, be configurable via UserPreferences ) |
|
430 |
|
|
431 |
=item - email, received by email and imported by hand or automatic. |
|
432 |
|
|
433 |
=back |
|
434 |
|
|
435 |
The files from source 'scanner' or 'email' are not allowed to delete else they must be send back to the sources. |
|
436 |
This means they are moved back into the correspondent source directories. |
|
437 |
|
|
438 |
The scanner and email import must be configured via Table UserPreferences: |
|
439 |
|
|
440 |
=begin text |
|
441 |
|
|
442 |
id | login | namespace | version | key | value |
|
443 |
----+---------+--------------+---------+----------+------------------------------------------------------ |
|
444 |
1 | default | file_sources | 0.00000 | scanner1 | {"dir":"/var/tmp/scanner1","desc":"Scanner Einkauf" } |
|
445 |
2 | default | file_sources | 0.00000 | emails | {"dir":"/var/tmp/emails" ,"desc":"Empfangene Mails"} |
|
446 |
|
|
447 |
=end text |
|
448 |
|
|
449 |
. |
|
450 |
|
|
451 |
The Fileinformation is stored in the table L<SL::DB::File> for saving the information. |
|
452 |
The modul and object_id describe the link to the object. |
|
453 |
|
|
454 |
The interface SL::File:Object encapsulate SL::DB:File, see L<SL::DB::Object> |
|
455 |
|
|
456 |
The storage backends are extra classes which depends from L<SL::File::Backend>. |
|
457 |
So additional backend classes can be added. |
|
458 |
|
|
459 |
The implementation of versioning is done in the different backends. |
|
460 |
|
|
461 |
=head1 METHODS |
|
462 |
|
|
463 |
=over 4 |
|
464 |
|
|
465 |
=item C<save> |
|
466 |
|
|
467 |
Creates a new SL::DB:File object or save an existing object for a specific backend depends of the C<file_type> |
|
468 |
and config, like |
|
469 |
|
|
470 |
=begin text |
|
471 |
|
|
472 |
SL::File->save( |
|
473 |
object_id => $self->object_id, |
|
474 |
object_type => $self->object_type, |
|
475 |
content_type => 'application/pdf' |
|
476 |
); |
|
477 |
|
|
478 |
=end text |
|
479 |
|
|
480 |
. |
|
481 |
|
|
482 |
The file data is stored in the backend. If the file_type is "document" and the source is not "created" the file is imported, |
|
483 |
so in the history the import is documented also as a hint to can unimport the file later. |
|
484 |
|
|
485 |
Available C<PARAMS>: |
|
486 |
|
|
487 |
=over 4 |
|
488 |
|
|
489 |
=item C<id> |
|
490 |
|
|
491 |
The id of SL::DB::File for an existing file |
|
492 |
|
|
493 |
=item C<object_id> |
|
494 |
|
|
495 |
The Id of the ERP-object for a new file. |
|
496 |
|
|
497 |
=item C<object_type> |
|
498 |
|
|
499 |
The Type of the ERP-object like "sales_quotation" for a new file. A clear mapping to the class/model exists in the controller. |
|
500 |
|
|
501 |
=item C<file_type> |
|
502 |
|
|
503 |
The type may be "documents", "attachments" or "images" for a new file. |
|
504 |
|
|
505 |
=item C<source> |
|
506 |
|
|
507 |
The type may be "created", "uploaded" or email sources or scanner sources for a new file. |
|
508 |
|
|
509 |
=item C<file_name> |
|
510 |
|
|
511 |
The file_name of the file for a new file. This name is used in the WebGUI and as name for download. |
|
512 |
|
|
513 |
=item C<mime_type> |
|
514 |
|
|
515 |
The mime_type of a new file. This is used for downloading or for email attachments. |
|
516 |
|
|
517 |
=item C<description> or C<title> |
|
518 |
|
|
519 |
The description or title of a new file. This must be discussed if this attribute is needed. |
|
520 |
|
|
521 |
=back |
|
522 |
|
|
523 |
=item C<delete PARAMS> |
|
524 |
|
|
525 |
The file data is deleted in the backend. If the file comes from source 'scanner' or 'email' |
|
526 |
they moved back to the source folders. This is documented in the history. |
|
527 |
|
|
528 |
Available C<PARAMS>: |
|
529 |
|
|
530 |
=over 4 |
|
531 |
|
|
532 |
=item C<id> |
|
533 |
|
|
534 |
The id of SL::DB::File |
|
535 |
|
|
536 |
=item C<dbfile> |
|
537 |
|
|
538 |
As alternative if the SL::DB::File as object is available. |
|
539 |
|
|
540 |
=back |
|
541 |
|
|
542 |
=item C<delete_all PARAMS> |
|
543 |
|
|
544 |
All file data of an ERP-object is deleted in the backend. |
|
545 |
|
|
546 |
=over 4 |
|
547 |
|
|
548 |
=item C<object_id> |
|
549 |
|
|
550 |
The Id of the ERP-object. |
|
551 |
|
|
552 |
=item C<object_type> |
|
553 |
|
|
554 |
The Type of the ERP-object like "sales_quotation". A clear mapping to the class/model exists in the controller. |
|
555 |
|
|
556 |
=back |
|
557 |
|
|
558 |
=item C<rename PARAMS> |
|
559 |
|
|
560 |
The Filename of the file is changed |
|
561 |
|
|
562 |
Available C<PARAMS>: |
|
563 |
|
|
564 |
=over 4 |
|
565 |
|
|
566 |
=item C<id> |
|
567 |
|
|
568 |
The id of SL::DB::File |
|
569 |
|
|
570 |
=item C<to> |
|
571 |
|
|
572 |
The new filename |
|
573 |
|
|
574 |
=back |
|
575 |
|
|
576 |
=item C<get PARAMS> |
|
577 |
|
|
578 |
The actual file object is retrieved. The id of the object is needed. |
|
579 |
|
|
580 |
Available C<PARAMS>: |
|
581 |
|
|
582 |
=over 4 |
|
583 |
|
|
584 |
=item C<id> |
|
585 |
|
|
586 |
The id of SL::DB::File |
|
587 |
|
|
588 |
=back |
|
589 |
|
|
590 |
=item C<get_all PARAMS> |
|
591 |
|
|
592 |
All last versions of file data objects which are related to an ERP-Document,Part,Customer,Vendor,... are retrieved. |
|
593 |
|
|
594 |
Available C<PARAMS>: |
|
595 |
|
|
596 |
=over 4 |
|
597 |
|
|
598 |
=item C<object_id> |
|
599 |
|
|
600 |
The Id of the ERP-object. |
|
601 |
|
|
602 |
=item C<object_type> |
|
603 |
|
|
604 |
The Type of the ERP-object like "sales_quotation". A clear mapping to the class/model exists in the controller. |
|
605 |
|
|
606 |
=item C<file_type> |
|
607 |
|
|
608 |
The type may be "documents", "attachments" or "images". This parameter is optional. |
|
609 |
|
|
610 |
=item C<file_name> |
|
611 |
|
|
612 |
The name of the file . This parameter is optional. |
|
613 |
|
|
614 |
=item C<mime_type> |
|
615 |
|
|
616 |
The MIME type of the file . This parameter is optional. |
|
617 |
|
|
618 |
=item C<source> |
|
619 |
|
|
620 |
The type may be "created", "uploaded" or email sources or scanner soureces. This parameter is optional. |
|
621 |
|
|
622 |
=item C<sort_by> |
|
623 |
|
|
624 |
An optional parameter in which sorting the files are retrieved. Default is decrementing itime and ascending filename |
|
625 |
|
|
626 |
=back |
|
627 |
|
|
628 |
=item C<get_all_versions PARAMS> |
|
629 |
|
|
630 |
All versions of file data objects which are related to an ERP-Document,Part,Customer,Vendor,... are retrieved. |
|
631 |
If only the versions of one file are wanted, additional parameter like file_name must be set. |
|
632 |
If the param C<dbfile> set, only the versions of this file are returned. |
|
633 |
|
|
634 |
Available C<PARAMS> ar the same as L<get_all> |
|
635 |
|
|
636 |
|
|
637 |
|
|
638 |
=item C<get_all_count PARAMS> |
|
639 |
|
|
640 |
The count of available files is returned. |
|
641 |
Available C<PARAMS> ar the same as L<get_all> |
|
642 |
|
|
643 |
|
|
644 |
=item C<get_content PARAMS> |
|
645 |
|
|
646 |
The data of a file can retrieved. A reference to the data is returned. |
|
647 |
|
|
648 |
Available C<PARAMS>: |
|
649 |
|
|
650 |
=over 4 |
|
651 |
|
|
652 |
=item C<id> |
|
653 |
|
|
654 |
The id of SL::DB::File |
|
655 |
|
|
656 |
=item C<dbfile> |
|
657 |
|
|
658 |
If no Id exists the object SL::DB::File as param. |
|
659 |
|
|
660 |
=back |
|
661 |
|
|
662 |
=item C<get_file_path PARAMS> |
|
663 |
|
|
664 |
Sometimes it is more useful to have a path to the file not the contents. If the backend has not stored the content as file |
|
665 |
it is in the responsibility of the backend to create a tempory session file. |
|
666 |
|
|
667 |
Available C<PARAMS>: |
|
668 |
|
|
669 |
=over 4 |
|
670 |
|
|
671 |
=item C<id> |
|
672 |
|
|
673 |
The id of SL::DB::File |
|
674 |
|
|
675 |
=item C<dbfile> |
|
676 |
|
|
677 |
If no Id exists the object SL::DB::File as param. |
|
678 |
|
|
679 |
=back |
|
680 |
|
|
681 |
=item C<get_other_sources> |
|
682 |
|
|
683 |
A helpful method to get the sources for scanner and email from UserPreferences. This method is need from SL::Controller::File |
|
684 |
|
|
685 |
=item C<sync_from_backend> |
|
686 |
|
|
687 |
For Backends which may be changed outside of kivitendo a synchronization of the database is done. |
|
688 |
This sync must be triggered by a periodical task. |
|
689 |
|
|
690 |
Needed C<PARAMS>: |
|
691 |
|
|
692 |
=over 4 |
|
693 |
|
|
694 |
=item C<file_type> |
|
695 |
|
|
696 |
The synchronization is done file_type by file_type. |
|
697 |
|
|
698 |
=back |
|
699 |
|
|
700 |
=back |
|
701 |
|
|
702 |
=head1 AUTHOR |
|
703 |
|
|
704 |
Martin Helmling E<lt>martin.helmling@opendynamic.deE<gt> |
|
705 |
|
|
706 |
=cut |
|
707 |
|
SL/File/Backend.pm | ||
---|---|---|
1 |
package SL::File::Backend; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use parent qw(Rose::Object); |
|
6 |
|
|
7 |
sub store { die 'store needs to be implemented' } |
|
8 |
|
|
9 |
sub delete { die 'delete needs to be implemented' } |
|
10 |
|
|
11 |
sub rename { die 'rename needs to be implemented' } |
|
12 |
|
|
13 |
sub get_content { die 'get_content needs to be implemented' } |
|
14 |
|
|
15 |
sub get_filepath { die 'get_filepath needs to be implemented' } |
|
16 |
|
|
17 |
sub get_mtime { die 'get_mtime needs to be implemented' } |
|
18 |
|
|
19 |
sub get_version_count { die 'get_version_count needs to be implemented' } |
|
20 |
|
|
21 |
sub enabled { 0; } |
|
22 |
|
|
23 |
sub sync_from_backend { } |
|
24 |
|
|
25 |
1; |
|
26 |
|
|
27 |
__END__ |
|
28 |
|
|
29 |
=pod |
|
30 |
|
|
31 |
=encoding utf8 |
|
32 |
|
|
33 |
=head1 NAME |
|
34 |
|
|
35 |
SL::File::Backend - Base class for file storage backend |
|
36 |
|
|
37 |
=head1 SYNOPSIS |
|
38 |
|
|
39 |
See the synopsis of L<SL::File> and L<SL::File::Object> |
|
40 |
|
|
41 |
=head1 OVERVIEW |
|
42 |
|
|
43 |
The most methods must be overridden by the specific storage backend |
|
44 |
|
|
45 |
See also the overview of L<SL::File> and L<SL::File::Object>. |
|
46 |
|
|
47 |
|
|
48 |
=head1 METHODS |
|
49 |
|
|
50 |
=over 4 |
|
51 |
|
|
52 |
=item C<store PARAMS> |
|
53 |
|
|
54 |
The file data is stored in the backend. |
|
55 |
|
|
56 |
Available C<PARAMS>: |
|
57 |
|
|
58 |
=over 4 |
|
59 |
|
|
60 |
=item C<dbfile> |
|
61 |
|
|
62 |
The object SL::DB::File as param. |
|
63 |
|
|
64 |
=item C<file_contents> |
|
65 |
|
|
66 |
The data of the file to store |
|
67 |
|
|
68 |
=item C<file_path> |
|
69 |
|
|
70 |
If the data is still in a file, the contents of this file is copied. |
|
71 |
|
|
72 |
=back |
|
73 |
|
|
74 |
If both parameter C<file_contents> and C<file_path> exists, |
|
75 |
the backend is responsible in which way the contents is fetched. |
|
76 |
|
|
77 |
If the file exists the backend is responsible to decide to save a new version of the file or override the |
|
78 |
latest existing file. |
|
79 |
|
|
80 |
=item C<delete PARAMS> |
|
81 |
|
|
82 |
The file data is deleted in the backend. |
|
83 |
|
|
84 |
Available C<PARAMS>: |
|
85 |
|
|
86 |
=over 4 |
|
87 |
|
|
88 |
=item C<dbfile> |
|
89 |
|
|
90 |
The object SL::DB::File as param. |
|
91 |
|
|
92 |
=item C<last> |
|
93 |
|
|
94 |
If this parameter is set only the latest version of the file are deleted. |
|
95 |
|
|
96 |
=item C<all_but_notlast> |
|
97 |
|
|
98 |
If this parameter is set all versions of the file are deleted except the latest version. |
|
99 |
|
|
100 |
If none of the two parameters C<all_versions> or C<all__but_notlast> is set |
|
101 |
all version of the file are deleted. |
|
102 |
|
|
103 |
=back |
|
104 |
|
|
105 |
=item C<rename PARAMS> |
|
106 |
|
|
107 |
The Filename of the file is changed. If the backend is not dependant from the filename |
|
108 |
nothing must happens. The rename must work on all versions of the file. |
|
109 |
|
|
110 |
Available C<PARAMS>: |
|
111 |
|
|
112 |
=over 4 |
|
113 |
|
|
114 |
=item C<dbfile> |
|
115 |
|
|
116 |
The object SL::DB::File as param. |
|
117 |
|
|
118 |
=back |
|
119 |
|
|
120 |
=item C<get_version_count PARAMS> |
|
121 |
|
|
122 |
The count of the available versions of a file will returned. |
|
123 |
The versions are numbered from 1 up to the returned value |
|
124 |
|
|
125 |
Available C<PARAMS>: |
|
126 |
|
|
127 |
=over 4 |
|
128 |
|
|
129 |
=item C<dbfile> |
|
130 |
|
|
131 |
=back |
|
132 |
|
|
133 |
=item C<get_mtime PARAMS> |
|
134 |
|
|
135 |
Available C<PARAMS>: |
|
136 |
|
|
137 |
=over 4 |
|
138 |
|
|
139 |
=item C<dbfile> |
|
140 |
|
|
141 |
The object SL::DB::File as param. |
|
142 |
|
|
143 |
=item C<version> |
|
144 |
|
|
145 |
The version number of the file for which the modification timestamp is wanted. |
|
146 |
If no version set or version is 0 , the mtime of the latest version is returned. |
|
147 |
|
|
148 |
=back |
|
149 |
|
|
150 |
=item C<get_content PARAMS> |
|
151 |
|
|
152 |
For downloading or printing the real data need to retrieve. |
|
153 |
A reference of the data must be returned. |
|
154 |
|
|
155 |
Available C<PARAMS>: |
|
156 |
|
|
157 |
=over 4 |
|
158 |
|
|
159 |
=item C<dbfile> |
|
160 |
|
|
161 |
The object SL::DB::File as param. |
|
162 |
|
|
163 |
=back |
|
164 |
|
|
165 |
=item C<get_file_path PARAMS> |
|
166 |
|
|
167 |
If the backend has files as storage, the file path can returned. |
|
168 |
If a file is not available in the backend a temporary file must be created with the contents. |
|
169 |
|
|
170 |
Available C<PARAMS>: |
|
171 |
|
|
172 |
=over 4 |
|
173 |
|
|
174 |
=item C<dbfile> |
|
175 |
|
|
176 |
The object SL::DB::File as param. |
|
177 |
|
|
178 |
=back |
|
179 |
|
|
180 |
=item C<enabled> |
|
181 |
|
|
182 |
returns 1 if the backend is enabled and has all config to work. |
|
183 |
In other cases it must return 0 |
|
184 |
|
|
185 |
=item C<sync_from_backend> |
|
186 |
|
|
187 |
For Backends which may be changed outside of kivitendo a synchronization of the database is done. |
|
188 |
Normally the backend is responsible to actualise the data if it needed. |
|
189 |
This interface can be used if a long work must be done and runs in a extra task. |
|
190 |
|
|
191 |
=back |
|
192 |
|
|
193 |
=head1 SEE ALSO |
|
194 |
|
|
195 |
L<SL::File>, L<SL::File::Object> |
|
196 |
|
|
197 |
=head1 AUTHOR |
|
198 |
|
|
199 |
Martin Helmling E<lt>martin.helmling@opendynamic.deE<gt> |
|
200 |
|
|
201 |
=cut |
|
202 |
|
|
203 |
|
SL/File/Object.pm | ||
---|---|---|
1 |
package SL::File::Object; |
|
2 |
|
|
3 |
use strict; |
|
4 |
use parent qw(Rose::Object); |
|
5 |
use DateTime; |
|
6 |
|
|
7 |
use Rose::Object::MakeMethods::Generic ( |
|
8 |
scalar => [ qw() ], |
|
9 |
'scalar --get_set_init' => [ qw(db_file loaded id version newest) ], |
|
10 |
); |
|
11 |
|
|
12 |
#use SL::DB::Helper::Attr; |
|
13 |
#__PACKAGE__->_as_timestamp('mtime'); |
|
14 |
# wie wird das mit dem Attr Helper gemacht damit er bei nicht DB Objekten auch geht? |
|
15 |
|
|
16 |
sub mtime_as_timestamp_s { |
|
17 |
$::locale->format_date_object($_[0]->mtime, precision => 'second'); |
|
18 |
} |
|
19 |
|
|
20 |
# wrapper methods |
|
21 |
|
|
22 |
sub itime { |
|
23 |
$_[0]->loaded_db_file->itime; |
|
24 |
} |
|
25 |
|
|
26 |
sub file_name { |
|
27 |
$_[0]->loaded_db_file->file_name; |
|
28 |
} |
|
29 |
|
|
30 |
sub file_type { |
|
31 |
$_[0]->loaded_db_file->file_type; |
|
32 |
} |
|
33 |
|
|
34 |
sub file_name { |
|
35 |
$_[0]->loaded_db_file->file_name; |
|
36 |
} |
|
37 |
|
|
38 |
sub object_type { |
|
39 |
$_[0]->loaded_db_file->object_type; |
|
40 |
} |
|
41 |
|
|
42 |
sub object_id { |
|
43 |
$_[0]->loaded_db_file->object_id; |
|
44 |
} |
|
45 |
|
|
46 |
sub mime_type { |
|
47 |
$_[0]->loaded_db_file->mime_type; |
|
48 |
} |
|
49 |
|
|
50 |
sub file_title { |
|
51 |
$_[0]->loaded_db_file->title; |
|
52 |
} |
|
53 |
|
|
54 |
sub file_description { |
|
55 |
$_[0]->loaded_db_file->description; |
|
56 |
} |
|
57 |
|
|
58 |
sub backend { |
|
59 |
$_[0]->loaded_db_file->backend; |
|
60 |
} |
|
61 |
|
|
62 |
sub source { |
|
63 |
$_[0]->loaded_db_file->source; |
|
64 |
} |
|
65 |
|
|
66 |
# methods to go directly into the backends |
|
67 |
|
|
68 |
sub get_file { |
|
69 |
$_[0]->backend_class->get_filepath(dbfile => $_[0]->loaded_db_file, version => $_[0]->version) |
|
70 |
} |
|
71 |
|
|
72 |
sub get_content { |
|
73 |
$_[0]->backend_class->get_content(dbfile => $_[0]->loaded_db_file, version => $_[0]->version) |
|
74 |
} |
|
75 |
|
|
76 |
sub mtime { |
|
77 |
$_[0]->backend_class->get_mtime(dbfile => $_[0]->loaded_db_file, version => $_[0]->version) |
|
78 |
} |
|
79 |
|
|
80 |
sub version_count { |
|
81 |
$_[0]->backend_class->get_version_count(dbfile => $_[0]->loaded_db_file) |
|
82 |
} |
|
83 |
|
|
84 |
sub versions { |
|
85 |
SL::File->get_all_versions(dbfile => $_[0]->loaded_db_file) |
|
86 |
} |
|
87 |
|
|
88 |
sub save_contents { |
|
89 |
SL::File->save(dbfile => $_[0]->loaded_db_file, file_contents => $_[1] ) |
|
90 |
} |
|
91 |
|
|
92 |
sub save_file { |
|
93 |
SL::File->save(dbfile => $_[0]->loaded_db_file, file_path => $_[1] ) |
|
94 |
} |
|
95 |
|
|
96 |
sub delete { |
|
97 |
SL::File->delete(dbfile => $_[0]->loaded_db_file) |
|
98 |
} |
|
99 |
|
|
100 |
sub delete_last_version { |
|
101 |
SL::File->delete(dbfile => $_[0]->loaded_db_file, last => 1 ) |
|
102 |
} |
|
103 |
|
|
104 |
sub purge { |
|
105 |
SL::File->delete(dbfile => $_[0]->loaded_db_file, all_but_notlast => 1 ) |
|
106 |
} |
|
107 |
|
|
108 |
sub rename { |
|
109 |
SL::File->rename(dbfile => $_[0]->loaded_db_file, to => $_[1]) |
|
110 |
} |
|
111 |
|
|
112 |
# internals |
|
113 |
|
|
114 |
sub backend_class { |
|
115 |
SL::File->get_backend_class($_[0]->backend) |
|
116 |
} |
|
117 |
|
|
118 |
|
|
119 |
sub loaded_db_file { # so, dass wir die nur einmal laden. |
|
120 |
if (!$_[0]->loaded) { |
|
121 |
$_[0]->db_file->load; |
|
122 |
$_[0]->loaded(1); |
|
123 |
} |
|
124 |
$_[0]->db_file; |
|
125 |
} |
|
126 |
|
|
127 |
|
|
128 |
sub init_db_file { die 'must always have a db file'; } |
|
129 |
sub init_loaded { 0 } |
|
130 |
sub init_id { 0 } |
|
131 |
sub init_version { 0 } |
|
132 |
sub init_newest { 1 } |
|
133 |
|
|
134 |
1; |
|
135 |
|
|
136 |
__END__ |
|
137 |
|
|
138 |
=encoding utf-8 |
|
139 |
|
|
140 |
=head1 NAME |
|
141 |
|
|
142 |
SL::File::Object - a filemangement object wrapper |
|
143 |
|
|
144 |
=head1 SYNOPSIS |
|
145 |
|
|
146 |
use SL::File; |
|
147 |
|
|
148 |
my ($object) = SL::File->get_all(object_id => $object_id, |
|
149 |
object_type => $object_type, |
|
150 |
file_type => 'images', # may be optional |
|
151 |
source => 'uploaded' # may be optional |
|
152 |
); |
|
153 |
# read attributes |
|
154 |
|
|
155 |
my $object_id = $object->object_id, |
|
156 |
my $object_type = $object->object_type, |
|
157 |
my $file_type = $object->file_type; |
|
158 |
my $file_name = $object->file_name; |
|
159 |
my $mime_type = $object->mime_type; |
|
160 |
|
|
161 |
my $mtime = $object->mtime; |
|
162 |
my $itime = $object->itime; |
|
163 |
my $id = $object->id; |
|
164 |
my $newest = $object->newest; |
|
165 |
|
|
166 |
my $versions = $object->version_count; |
|
167 |
|
|
168 |
my @versionobjs = $object->versions; |
|
169 |
foreach ( @versionobjs ) { |
|
170 |
my $mtime = $_->mtime; |
|
171 |
my $contents = $_->get_content; |
|
172 |
} |
|
173 |
|
|
174 |
# update |
|
175 |
|
|
176 |
$object->rename("image1.png"); |
|
177 |
$object->save_contents("new text"); |
|
178 |
$object->save_file("/tmp/empty.png"); |
|
179 |
$object->purge; |
|
180 |
$object->delete_last_version; |
|
181 |
$object->delete; |
|
182 |
|
|
183 |
=head1 DESCRIPTION |
|
184 |
|
|
185 |
This is a wrapper around a single object in the filemangement. |
|
186 |
|
|
187 |
=head1 METHODS |
|
188 |
|
|
189 |
Following methods are wrapper to read the attributes of L<SL::DB::File> : |
|
190 |
|
|
191 |
=over 4 |
|
192 |
|
|
193 |
=item C<object_id> |
|
194 |
|
|
195 |
=item C<object_type> |
|
196 |
|
|
197 |
=item C<file_type> |
|
198 |
|
|
199 |
=item C<file_name> |
|
200 |
|
|
201 |
=item C<mime_name> |
|
202 |
|
|
203 |
=item C<file_title> |
|
204 |
|
|
205 |
=item C<file_description> |
|
206 |
|
|
207 |
=item C<backend> |
|
208 |
|
|
209 |
=item C<source> |
|
210 |
|
|
211 |
=item C<itime> |
|
212 |
|
|
213 |
=item C<id> |
|
214 |
|
|
215 |
=back |
|
216 |
|
|
217 |
Additional are there special methods. If the Object is created by SL::File::get_all_versions() |
|
218 |
or by "$object->versions" |
|
219 |
it has a version number. So the different mtime, filepath or content can be retrieved: |
|
220 |
|
|
221 |
=over 4 |
|
222 |
|
|
223 |
=item C<mtime> |
|
224 |
|
|
225 |
get the modification time of a (versioned) object |
|
226 |
|
|
227 |
=item C<get_file> |
|
228 |
|
|
229 |
get the full qualified file path of the (versioned) object |
|
230 |
|
|
231 |
=item C<get_content> |
|
232 |
|
|
233 |
get the content of the (versioned) object |
|
234 |
|
|
235 |
=item C<version_count> |
|
236 |
|
|
237 |
Get the available versions of the file |
|
238 |
|
|
239 |
=item C<versions> |
|
240 |
|
|
241 |
Returns an array of SL::File::Object objects with the available versions of the file, starting with the newest version. |
|
242 |
|
|
243 |
=item C<newest> |
|
244 |
|
|
245 |
If set this is the newest version of the file. |
|
246 |
|
|
247 |
=item C<save_contents $contents> |
|
248 |
|
|
249 |
Store a new contents to the file (as a new version). |
|
250 |
|
|
251 |
=item C<save_file $filepath> |
|
252 |
|
|
253 |
Store the content of an (absolute)file path to the file |
|
254 |
|
|
255 |
=item C<delete> |
|
256 |
|
|
257 |
Delete the file with all of his versions |
|
258 |
|
|
259 |
=item C<delete_last_version> |
|
260 |
|
|
261 |
Delete only the last version of the file with implicit decrement of the version_count. |
|
262 |
|
|
263 |
=item C<purge> |
|
264 |
|
|
265 |
Delete all old versions of the file. Only one version exist after purge. The version count is reset to 1. |
|
266 |
|
|
267 |
=item C<rename $newfilename> |
|
268 |
|
|
269 |
Renames the filename |
|
270 |
|
|
271 |
=back |
|
272 |
|
|
273 |
=head1 SEE ALSO |
|
274 |
|
|
275 |
L<SL::File> |
|
276 |
|
|
277 |
=head1 AUTHOR |
|
278 |
|
|
279 |
Martin Helmling E<lt>martin.helmling@opendynamic.deE<gt> |
|
280 |
|
|
281 |
=cut |
Auch abrufbar als: Unified diff
Dateimanagement: Basiserweiterung
In diesem Commit sind die Anpassungen in der Mandantenkonfiguration
sowie die notwendigen Klassen und Controller.
Über eine Zwischenschicht wird das tatsächliche Backend (Dateien,WebDAV,ext.DMS,Datenbank etc) verborgen.