Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 8c7f25bc

Von Martin Helmling martin.helmling@octosoft.eu vor fast 8 Jahren hinzugefügt

  • ID 8c7f25bcd4da160b26527fa23a2e598476dc052d
  • Vorgänger 2bb452ee
  • Nachfolger 1ce68041

Dateimanagement: Backend "Filesystem"

mit test

Unterschiede anzeigen:

SL/File/Backend/Filesystem.pm
1
package SL::File::Backend::Filesystem;
2

  
3
use strict;
4

  
5
use parent qw(SL::File::Backend);
6
use SL::DB::File;
7
use File::Copy;
8
use File::Slurp;
9
use File::Path qw(make_path);
10

  
11
#
12
# public methods
13
#
14

  
15
sub delete {
16
  my ($self, %params) = @_;
17
  $main::lxdebug->message(LXDebug->DEBUG2(), "del in backend " . $self . "  file " . $params{dbfile});
18
  $main::lxdebug->message(LXDebug->DEBUG2(), "file id=" . ($params{dbfile}->id * 1));
19
  die "no dbfile" unless $params{dbfile};
20
  my $backend_data = $params{dbfile}->backend_data;
21
  $backend_data    = 0                               if $params{last};
22
  $backend_data    = $params{dbfile}->backend_data-1 if $params{all_but_notlast};
23

  
24
  if ($backend_data > 0 ) {
25
    $main::lxdebug->message(LXDebug->DEBUG2(), "backend_data=" .$backend_data);
26
    for my $version ( 1..$backend_data) {
27
      my $file_path = $self->_filesystem_path($params{dbfile},$version);
28
      $main::lxdebug->message(LXDebug->DEBUG2(), "unlink " .$file_path);
29
      unlink($file_path);
30
    }
31
    if ($params{all_but_notlast}) {
32
      my $from = $self->_filesystem_path($params{dbfile},$params{dbfile}->backend_data);
33
      my $to   = $self->_filesystem_path($params{dbfile},$params{dbfile}->backend_data);
34
      die "file not exists" unless -f $from;
35
      rename($from,$to);
36
      $params{dbfile}->backend_data(1);
37
    } else {
38
      $params{dbfile}->backend_data(0);
39
      my $dir_path = $self->_filesystem_path($params{dbfile});
40
      rmdir($dir_path);
41
      $main::lxdebug->message(LXDebug->DEBUG2(), "unlink " .$dir_path);
42
    }
43
  } else {
44
    my $file_path = $self->_filesystem_path($params{dbfile},$params{dbfile}->backend_data);
45
    die "file not exists" unless -f $file_path;
46
    unlink($file_path);
47
    $params{dbfile}->backend_data($params{dbfile}->backend_data-1);
48
  }
49
}
50

  
51
sub rename {
52
}
53

  
54
sub save {
55
  my ($self, %params) = @_;
56
  die 'dbfile not exists' unless $params{dbfile};
57
  $main::lxdebug->message(LXDebug->DEBUG2(), "in backend " . $self . "  file " . $params{dbfile});
58
  $main::lxdebug->message(LXDebug->DEBUG2(), "file id=" . $params{dbfile}->id . " path=" . $params{file_path});
59
  my $dbfile = $params{dbfile};
60
  die 'no file contents' unless $params{file_path} || $params{file_contents};
61
  $dbfile->backend_data(0) unless $dbfile->backend_data;
62
  $dbfile->backend_data($dbfile->backend_data*1+1);
63
  $dbfile->save->load;
64

  
65
  my $tofile = $self->_filesystem_path($dbfile);
66
  $main::lxdebug->message(LXDebug->DEBUG2(), "topath=" . $tofile . " from=" . $params{file_path});
67
  if ($params{file_path} && -f $params{file_path}) {
68
    File::Copy::copy($params{file_path}, $tofile);
69
  }
70
  elsif ($params{file_contents}) {
71
    open(OUT, "> " . $tofile);
72
    print OUT $params{file_contents};
73
    close(OUT);
74
  }
75
  return 1;
76
}
77

  
78
sub get_version_count {
79
  my ($self, %params) = @_;
80
  die "no dbfile" unless $params{dbfile};
81
  return $params{dbfile}->backend_data * 1;
82
}
83

  
84
sub get_mtime {
85
  my ($self, %params) = @_;
86
  die "no dbfile" unless $params{dbfile};
87
  $main::lxdebug->message(LXDebug->DEBUG2(), "version=" .$params{version});
88
  die "unknown version" if $params{version} && 
89
                          ($params{version} < 0 || $params{version} > $params{dbfile}->backend_data) ;
90
  my $path = $self->_filesystem_path($params{dbfile},$params{version});
91
  die "no file found in backend" if !-f $path;
92
  my @st = stat($path);
93
  my $dt = DateTime->from_epoch(epoch => $st[9])->clone();
94
  $main::lxdebug->message(LXDebug->DEBUG2(), "dt=" .$dt);
95
  return $dt;
96
}
97

  
98
sub get_filepath {
99
  my ($self, %params) = @_;
100
  die "no dbfile" unless $params{dbfile};
101
  my $path = $self->_filesystem_path($params{dbfile},$params{version});
102
  die "no file" if !-f $path;
103
  return $path;
104
}
105

  
106
sub get_content {
107
  my ($self, %params) = @_;
108
  my $path = $self->get_filepath(%params);
109
  return "" unless $path;
110
  my $contents = File::Slurp::read_file($path);
111
  return \$contents;
112
}
113

  
114
sub enabled {
115
  return 0 unless $::instance_conf->get_doc_files || $::instance_conf->get_doc_files_rootpath;
116
  $main::lxdebug->message(LXDebug->DEBUG2(), "root path=" . $::instance_conf->get_doc_files_rootpath . " isdir=" .( -d $::instance_conf->get_doc_files_rootpath?"YES":"NO"));
117
  return 0 unless -d $::instance_conf->get_doc_files_rootpath;
118
  return 1;
119
}
120

  
121

  
122
#
123
# internals
124
#
125

  
126
sub _filesystem_path {
127
  my ($self, $dbfile, $version) = @_;
128

  
129
  die "No files backend enabled" unless $::instance_conf->get_doc_files || $::instance_conf->get_doc_files_rootpath;
130

  
131
  # use filesystem with depth 3
132
  $version    = $dbfile->backend_data if !$version || $version < 1 || $version > $dbfile->backend_data;
133
  my $iddir   = sprintf("%04d", $dbfile->id % 1000);
134
  my $path    = File::Spec->catdir($::instance_conf->get_doc_files_rootpath, $iddir, $dbfile->id);
135
  $main::lxdebug->message(LXDebug->DEBUG2(), "file path=" .$path." id=" .$dbfile->id." version=".$version." basename=".$dbfile->id . '_' . $version);
136
  if (!-d $path) {
137
    File::Path::make_path($path, { chmod => 0770 });
138
  }
139
  return $path if !$version;
140
  return File::Spec->catdir($path, $dbfile->id . '_' . $version);
141
}
142

  
143
1;
144

  
145
__END__
146

  
147
=pod
148

  
149
=encoding utf8
150

  
151
=head1 NAME
152

  
153
SL::File::Backend::Filesystem  - Filesystem class for file storage backend
154

  
155
=head1 SYNOPSIS
156

  
157
See the synopsis of L<SL::File::Backend>.
158

  
159
=head1 OVERVIEW
160

  
161
This specific storage backend use a Filesystem which is only accessed by this interface.
162
This is the big difference to the Webdav backend where the files can be accessed without the control of that backend.
163
This backend use the database id of the SL::DB::File object as filename. The filesystem has up to 1000 subdirectories
164
to store the files not to flat in the filesystem. In this Subdirectories for each file an additional subdirectory exists
165
for the versions of this file.
166

  
167
The Versioning is done via a Versionnumber which is incremented by one for each version.
168
So the Version 2 of the file with the database id 4 is stored as path {root}/0004/4/4_2.
169

  
170

  
171
=head1 METHODS
172

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

  
175
=head1 SEE ALSO
176

  
177
L<SL::File::Backend>
178

  
179
=head1 AUTHOR
180

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

  
183
=cut
184

  
185

  
t/file/filesystem.t
1
use strict;
2
use Test::More tests => 11;
3

  
4
use lib 't';
5
use Support::TestSetup;
6
use Test::Exception;
7
use SL::File;
8
use SL::Dev::File;
9

  
10
Support::TestSetup::login();
11

  
12
my $db = SL::DB::Object->new->db;
13
$db->dbh->do("UPDATE defaults SET doc_files = 't'");
14
$db->dbh->do("UPDATE defaults SET doc_files_rootpath = '/var/tmp/kivifs'");
15

  
16
my $scannerfile = '/var/tmp/f2';
17

  
18
clear_up();
19
reset_state();
20

  
21
my $file1 = SL::Dev::File::create_uploaded( file_name => 'file1', file_contents => 'inhalt1 uploaded' );
22
my $file2 = SL::Dev::File::create_scanned(  file_name => 'file2', file_contents => 'inhalt2 scanned', file_path => $scannerfile );
23
my $file3 = SL::Dev::File::create_created(  file_name => 'file3', file_contents => 'inhalt3 created'    );
24
my $file4 = SL::Dev::File::create_created(  file_name => 'file3', file_contents => 'inhalt3 new version');
25

  
26
is( SL::Dev::File->get_all_count(),                    3,"total number of files created is 3");
27
ok( $file1->file_name                        eq 'file1' ,"file has right name");
28
my $content1 = $file1->get_content;
29
ok( $$content1 eq 'inhalt1 uploaded'                    ,"file has right content");
30

  
31
is( -f $scannerfile ? 1 : 0,                           0,"scanned document is moved from scanner");
32

  
33
$file2->delete;
34
is( -f $scannerfile ? 1 : 0,                           1,"scanned document is moved back to scanner");
35
my $content2 = File::Slurp::read_file($scannerfile);
36
ok( $content2 eq 'inhalt2 scanned'                      ,"scanned file has right content");
37

  
38
my @file5 = SL::Dev::File->get_all(file_name => 'file3');
39
is(   scalar( @file5),                                 1, "one actual file found");
40
my $content5 = $file5[0]->get_content();
41
ok( $$content5 eq 'inhalt3 new version'                 ,"file has right actual content");
42

  
43
my @file6 = SL::Dev::File->get_all_versions(file_name => 'file3');
44
is(   scalar( @file6),                                 2,"two file versions found");
45
$content5 = $file6[0]->get_content;
46
ok( $$content5 eq 'inhalt3 new version'                 ,"file has right actual content");
47
$content5 = $file6[1]->get_content;
48
ok( $$content5 eq 'inhalt3 created'                     ,"file has right old content");
49

  
50
print "\n\nController:\n";
51
# now test controller
52
#$::form->{object_id}  = 1;
53
#$::form->{object_type}= 'sales_order';
54
#$::form->{file_type}  = 'document';
55
$::form->{id}  = $file1->id;
56
print "id=".$::form->{id}."\n";
57
use SL::Controller::File;
58
SL::Controller::File->action_download();
59
$::form->{object_id}   = 12345678;
60
$::form->{object_type} = undef;
61
eval {
62
  SL::Controller::File->check_object_params();
63
  1;
64
} or do {
65
    print $@;
66
};
67
$::form->{object_type} ='xx';
68
$::form->{file_type} ='yy';
69
eval {
70
  SL::Controller::File->check_object_params();
71
  1;
72
} or do {
73
    print $@;
74
};
75

  
76
clear_up();
77
done_testing;
78

  
79
sub clear_up {
80
  SL::Dev::File->delete_all();
81
  unlink($scannerfile);
82
};
83

  
84
sub reset_state {
85
  my %params = @_;
86

  
87
};
88

  
89
1;

Auch abrufbar als: Unified diff