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