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