File Coverage

blib/lib/DBIx/Class/InflateColumn/File.pm
Criterion Covered Total %
statement 66 66 100.0
branch 7 10 70.0
condition 3 6 50.0
subroutine 17 17 100.0
pod 3 3 100.0
total 96 102 94.1


line stmt bran cond sub pod time code
1             package DBIx::Class::InflateColumn::File;
2              
3 3     3   2488 use strict;
  3         8  
  3         105  
4 3     3   19 use warnings;
  3         5  
  3         115  
5 3     3   16 use base 'DBIx::Class';
  3         5  
  3         301  
6 3     3   19 use File::Path;
  3         5  
  3         213  
7 3     3   1887 use File::Copy;
  3         7343  
  3         175  
8 3     3   19 use Path::Class;
  3         5  
  3         152  
9 3     3   15 use DBIx::Class::Carp;
  3         9  
  3         24  
10 3     3   16 use namespace::clean;
  3         7  
  3         23  
11              
12             carp 'InflateColumn::File has entered a deprecation cycle. This component '
13             .'has a number of architectural deficiencies that can quickly drive '
14             .'your filesystem and database out of sync and is not recommended '
15             .'for further use. It will be retained for backwards '
16             .'compatibility, but no new functionality patches will be accepted. '
17             .'Please consider using the much more mature and actively maintained '
18             .'DBIx::Class::InflateColumn::FS. You can set the environment variable '
19             .'DBIC_IC_FILE_NOWARN to a true value to disable this warning.'
20             unless $ENV{DBIC_IC_FILE_NOWARN};
21              
22              
23              
24             __PACKAGE__->load_components(qw/InflateColumn/);
25              
26             sub register_column {
27 2     2 1 6 my ($self, $column, $info, @rest) = @_;
28 2         9 $self->next::method($column, $info, @rest);
29 2 100       876 return unless defined($info->{is_file_column});
30              
31             $self->inflate_column($column => {
32             inflate => sub {
33 3     3   4 my ($value, $obj) = @_;
34 3         7 $obj->_inflate_file_column($column, $value);
35             },
36             deflate => sub {
37 1     1   2 my ($value, $obj) = @_;
38 1         3 $obj->_save_file_column($column, $value);
39             },
40 1         24 });
41             }
42              
43             sub _file_column_file {
44 7     7   12 my ($self, $column, $filename) = @_;
45              
46 7         13 my $column_info = $self->result_source->column_info($column);
47              
48 7 50       16 return unless $column_info->{is_file_column};
49              
50             # DO NOT CHANGE
51             # This call to id() is generally incorrect - will not DTRT on
52             # multicolumn key. However changing this may introduce
53             # backwards-comp regressions, thus leaving as is
54 7   33     142 my $id = $self->id || $self->throw_exception(
55             'id required for filename generation'
56             );
57              
58 7   66     29 $filename ||= $self->$column->{filename};
59             return Path::Class::file(
60 7         20 $column_info->{file_column_path}, $id, $filename,
61             );
62             }
63              
64             sub delete {
65 1     1 1 1096 my ( $self, @rest ) = @_;
66              
67 1         4 my $colinfos = $self->result_source->columns_info;
68              
69 1         4 for ( keys %$colinfos ) {
70 1 50       4 if ( $colinfos->{$_}{is_file_column} ) {
71 1         3 rmtree( [$self->_file_column_file($_)->dir], 0, 0 );
72 1         554 last; # if we've deleted one, we've deleted them all
73             }
74             }
75              
76 1         5 return $self->next::method(@rest);
77             }
78              
79             sub insert {
80 2     2 1 3 my $self = shift;
81              
82             # cache our file columns so we can write them to the fs
83             # -after- we have a PK
84 2         5 my $colinfos = $self->result_source->columns_info;
85              
86 2         5 my %file_column;
87 2         4 for ( keys %$colinfos ) {
88 4 100       11 if ( $colinfos->{$_}{is_file_column} ) {
89 2         48 $file_column{$_} = $self->$_;
90 2         34 $self->store_column($_ => $self->$_->{filename});
91             }
92             }
93              
94 2         9 $self->next::method(@_);
95              
96             # write the files to the fs
97 2         9 while ( my ($col, $file) = each %file_column ) {
98 2         10 $self->_save_file_column($col, $file);
99             }
100              
101 2         8 return $self;
102             }
103              
104              
105             sub _inflate_file_column {
106 3     3   5 my ( $self, $column, $value ) = @_;
107              
108 3         5 my $fs_file = $self->_file_column_file($column, $value);
109              
110 3         204 return { handle => $fs_file->open('r'), filename => $value };
111             }
112              
113             sub _save_file_column {
114 3     3   4 my ( $self, $column, $value ) = @_;
115              
116 3 50       7 return unless ref $value;
117              
118 3         18 my $fs_file = $self->_file_column_file($column, $value->{filename});
119 3         180 mkpath [$fs_file->dir];
120              
121             # File::Copy doesn't like Path::Class (or any for that matter) objects,
122             # thus ->stringify (http://rt.perl.org/rt3/Public/Bug/Display.html?id=59650)
123 3         478 File::Copy::copy($value->{handle}, $fs_file->stringify);
124              
125 3         878 $self->_file_column_callback($value, $self, $column);
126              
127 3         46 return $value->{filename};
128             }
129              
130             =head1 NAME
131              
132             DBIx::Class::InflateColumn::File - DEPRECATED (superseded by DBIx::Class::InflateColumn::FS)
133              
134             =head2 Deprecation Notice
135              
136             This component has a number of architectural deficiencies that can quickly
137             drive your filesystem and database out of sync and is not recommended for
138             further use. It will be retained for backwards compatibility, but no new
139             functionality patches will be accepted. Please consider using the much more
140             mature and actively supported DBIx::Class::InflateColumn::FS. You can set
141             the environment variable DBIC_IC_FILE_NOWARN to a true value to disable
142             this warning.
143              
144             =head1 SYNOPSIS
145              
146             In your L table class:
147              
148             use base 'DBIx::Class::Core';
149              
150             __PACKAGE__->load_components(qw/InflateColumn::File/);
151              
152             # define your columns
153             __PACKAGE__->add_columns(
154             "id",
155             {
156             data_type => "integer",
157             is_auto_increment => 1,
158             is_nullable => 0,
159             size => 4,
160             },
161             "filename",
162             {
163             data_type => "varchar",
164             is_file_column => 1,
165             file_column_path =>'/tmp/uploaded_files',
166             # or for a Catalyst application
167             # file_column_path => MyApp->path_to('root','static','files'),
168             default_value => undef,
169             is_nullable => 1,
170             size => 255,
171             },
172             );
173              
174              
175             In your L class:
176              
177             FileColumn requires a hash that contains L as handle and the file's
178             name as name.
179              
180             my $entry = $c->model('MyAppDB::Articles')->create({
181             subject => 'blah',
182             filename => {
183             handle => $c->req->upload('myupload')->fh,
184             filename => $c->req->upload('myupload')->basename
185             },
186             body => '....'
187             });
188             $c->stash->{entry}=$entry;
189              
190              
191             And Place the following in your TT template
192              
193             Article Subject: [% entry.subject %]
194             Uploaded File:
195             File
196             Body: [% entry.body %]
197              
198             The file will be stored on the filesystem for later retrieval. Calling delete
199             on your resultset will delete the file from the filesystem. Retrevial of the
200             record automatically inflates the column back to the set hash with the
201             IO::File handle and filename.
202              
203             =head1 DESCRIPTION
204              
205             InflateColumn::File
206              
207             =head1 METHODS
208              
209             =head2 _file_column_callback ($file,$ret,$target)
210              
211             Method made to be overridden for callback purposes.
212              
213             =cut
214              
215       3     sub _file_column_callback {}
216              
217             =head1 FURTHER QUESTIONS?
218              
219             Check the list of L.
220              
221             =head1 COPYRIGHT AND LICENSE
222              
223             This module is free software L
224             by the L. You can
225             redistribute it and/or modify it under the same terms as the
226             L.
227              
228             =cut
229              
230             1;