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