committing first version of filecolumn
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / FileColumn.pm
CommitLineData
4740bdb7 1package DBIx::Class::FileColumn;
2
3use strict;
4use warnings;
5use base 'DBIx::Class';
6use File::Path;
7use File::Copy;
8use IO::File;
9
10sub inflate_result {
11 my $self = shift;
12 my $ret = $self->next::method(@_);
13
14 $self->_inflate_file_column($ret);
15 return $ret;
16}
17
18sub insert {
19 my ( $self, @rest ) = @_;
20
21 my ( $file, @column_names ) = $self->_load_file_column_information;
22 my $ret = $self->next::method(@rest);
23 $self->_save_file_column( $file, $ret, @column_names );
24 return $ret;
25}
26
27sub update {
28 my ($self, @rest ) = @_;
29
30 my ( $file, @column_names ) = $self->_load_file_column_information;
31 my $ret = $self->next::method(@rest);
32 $self->_save_file_column( $file, $ret, @column_names );
33 return $ret;
34}
35
36sub delete {
37 my ( $self, @rest ) = @_;
38
39 my @column_names = $self->columns;
40 for (@column_names) {
41 if ( $self->column_info($_)->{is_file_column} ) {
42 my $path =
43 File::Spec->catdir( $self->column_info($_)->{file_column_path},
44 $self->id );
45 rmtree( [$path], 0, 0 );
46 }
47 }
48
49 my $ret = $self->next::method(@rest);
50
51 return $ret;
52}
53
54sub _inflate_file_column {
55 my $self = shift;
56 my $ret = shift;
57
58 my @column_names = $self->columns;
59 for(@column_names) {
60 if ( $ret->column_info($_)->{is_file_column} ) {
61 # make sure everything checks out
62 unless (defined $ret->$_) {
63 # if something is wrong set it to undef
64 $ret->$_(undef);
65 next;
66 }
67 my $fs_file =
68 File::Spec->catfile( $ret->column_info($_)->{file_column_path},
69 $ret->id, $ret->$_ );
70 $ret->$_({handle => new IO::File($fs_file, "r"), filename => $ret->$_});
71 }
72 }
73}
74
75sub _load_file_column_information {
76 my $self = shift;
77
78 my $file;
79 my @column_names;
80
81 @column_names = $self->columns;
82 for (@column_names) {
83 if ( $self->column_info($_)->{is_file_column} ) {
84 # make sure everything checks out
85 unless ((defined $self->$_) ||
86 (defined $self->$_->{filename} && defined $self->$_->{handle})) {
87 # if something is wrong set it to undef
88 $self->$_(undef);
89 next;
90 }
91 $file->{$_} = $self->$_;
92 $self->$_( $self->$_->{filename} );
93 }
94 }
95
96 return ( $file, @column_names );
97}
98
99sub _save_file_column {
100 my ( $self, $file, $ret, @column_names ) = @_;
101
102 for (@column_names) {
103 if ( $ret->column_info($_)->{is_file_column} ) {
104 next unless (defined $ret->$_);
105 my $file_path =
106 File::Spec->catdir( $ret->column_info($_)->{file_column_path},
107 $ret->id );
108 mkpath [$file_path];
109
110 my $outfile =
111 File::Spec->catfile( $file_path, $file->{$_}->{filename} );
112 File::Copy::copy( $file->{$_}->{handle}, $outfile );
113 }
114 }
115}
116
117=head1 NAME
118
119DBIx::Class::FileColumn - FileColumn map files from the Database to the filesystem.
120
121=head1 DESCRIPTION
122
123FileColumn
124
125=head1 SYNOPSIS
126
127In your L<DBIx::Class> table class:
128
129 __PACKAGE__->load_components( "PK::Auto", "FileColumn", "Core" );
130
131 # define your columns
132 __PACKAGE__->add_columns(
133 "id",
134 {
135 data_type => "integer",
136 is_auto_increment => 1,
137 is_nullable => 0,
138 size => 4,
139 },
140 "filename",
141 {
142 data_type => "varchar",
143 is_file_column => 1,
144 file_column_path =>'/tmp/uploaded_files',
145 # or for a Catalyst application
146 # file_column_path => MyApp->path_to('root','static','files'),
147 default_value => undef,
148 is_nullable => 1,
149 size => 255,
150 },
151 );
152
153
154In your L<Catalyst::Controller> class:
155
156FileColumn requires a hash that contains L<IO::File> as handle and the file's name as name.
157
158 my $entry = $c->model('MyAppDB::Articles')->create({
159 subject => 'blah',
160 filename => {
161 handle => $c->req->upload('myupload')->fh,
162 filename => $c->req->upload('myupload')->basename
163 },
164 body => '....'
165 });
166 $c->stash->{entry}=$entry;
167
168
169And Place the following in your TT template
170
171 Article Subject: [% entry.subject %]
172 Uploaded File:
173 <a href="/static/files/[% entry.id %]/[% entry.filename.filename %]">File</a>
174 Body: [% entry.body %]
175
176The file will be stored on the filesystem for later retrieval.
177Calling delete on your resultset will delete the file from the filesystem.
178Retrevial of the record automatically inflates the column back to the set hash with the IO::File handle and filename.
179
180=head1 AUTHOR
181
182Victor Igumnov
183
184=head1 LICENSE
185
186This library is free software, you can redistribute it and/or modify
187it under the same terms as Perl itself.
188
189=cut
190
1911;