X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FInflateColumn%2FFile.pm;h=19011875a9dd81621fd3219a58e482a21176bf4a;hb=d4daee7b54e38e4b3d3d0a77759bddc1a4ede6e5;hp=1d76befcc06908ecd4d1b26ab1e751f5177558b9;hpb=28d4067a8514340167194b3397931a6cdb93be26;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/InflateColumn/File.pm b/lib/DBIx/Class/InflateColumn/File.pm index 1d76bef..1901187 100644 --- a/lib/DBIx/Class/InflateColumn/File.pm +++ b/lib/DBIx/Class/InflateColumn/File.pm @@ -1,143 +1,120 @@ -package DBIx::Class::File; +package DBIx::Class::InflateColumn::File; use strict; use warnings; use base 'DBIx::Class'; use File::Path; use File::Copy; -use IO::File; +use Path::Class; __PACKAGE__->load_components(qw/InflateColumn/); - sub register_column { - my ($self, $column, $info, @rest) = @_; - $self->next::method($column, $info, @rest); - return unless defined($info->{is_file_column}); - $self->inflate_column( - $column => - { - inflate => $self->_inflate_file_column, - deflate => sub { - my ( $file, @column_names ) = $self->_load_file_column_information; - $self->_save_file_column( $file, $self, @column_names ); - }, - } - ); + my ($self, $column, $info, @rest) = @_; + $self->next::method($column, $info, @rest); + return unless defined($info->{is_file_column}); + + $self->inflate_column($column => { + inflate => sub { + my ($value, $obj) = @_; + $obj->_inflate_file_column($column, $value); + }, + deflate => sub { + my ($value, $obj) = @_; + $obj->_save_file_column($column, $value); + }, + }); } +sub _file_column_file { + my ($self, $column, $filename) = @_; -sub delete { - my ( $self, @rest ) = @_; + my $column_info = $self->column_info($column); - my @column_names = $self->columns; - for (@column_names) { - if ( $self->column_info($_)->{is_file_column} ) { - my $path = - File::Spec->catdir( $self->column_info($_)->{file_column_path}, - $self->id ); - rmtree( [$path], 0, 0 ); - } - } + return unless $column_info->{is_file_column}; - my $ret = $self->next::method(@rest); + my $id = $self->id || $self->throw_exception( + 'id required for filename generation' + ); - return $ret; + $filename ||= $self->$column->{filename}; + return Path::Class::file( + $column_info->{file_column_path}, $id, $filename, + ); } -sub _inflate_file_column { - my $self = shift; +sub delete { + my ( $self, @rest ) = @_; - my @column_names = $self->columns; - for(@column_names) { + for ( $self->columns ) { if ( $self->column_info($_)->{is_file_column} ) { - # make sure everything checks out - unless (defined $self->$_) { - # if something is wrong set it to undef - $self->$_(undef); - next; - } - my $fs_file = - File::Spec->catfile( $self->column_info($_)->{file_column_path}, - $self->id, $self->$_ ); - $self->$_({handle => new IO::File($fs_file, "r"), filename => $self->$_}); + rmtree( [$self->_file_column_file($_)->dir], 0, 0 ); + last; # if we've deleted one, we've deleted them all } } + + return $self->next::method(@rest); } -sub _load_file_column_information { +sub insert { my $self = shift; - my $file; - my @column_names; - - @column_names = $self->columns; - for (@column_names) { + # cache our file columns so we can write them to the fs + # -after- we have a PK + my %file_column; + for ( $self->columns ) { if ( $self->column_info($_)->{is_file_column} ) { - # make sure everything checks out - unless ((defined $self->$_) || - (defined $self->$_->{filename} && defined $self->$_->{handle})) { - # if something is wrong set it to undef - $self->$_(undef); - next; - } - $file->{$_} = $self->$_; - $self->$_( $self->$_->{filename} ); + $file_column{$_} = $self->$_; + $self->store_column($_ => $self->$_->{filename}); } } - return ( $file, @column_names ); -} + $self->next::method(@_); -sub _save_file_column { - my ( $self, $file, $ret, @column_names ) = @_; - - for (@column_names) { - if ( $ret->column_info($_)->{is_file_column} ) { - next unless (defined $ret->$_); - my $file_path = - File::Spec->catdir( $ret->column_info($_)->{file_column_path}, - $ret->id ); - mkpath [$file_path]; - - my $outfile = - File::Spec->catfile( $file_path, $file->{$_}->{filename} ); - File::Copy::copy( $file->{$_}->{handle}, $outfile ); - - $self->_file_column_callback($file->{$_},$ret,$_); - } + # write the files to the fs + while ( my ($col, $file) = each %file_column ) { + $self->_save_file_column($col, $file); } + + return $self; } -=head1 METHODS -=cut +sub _inflate_file_column { + my ( $self, $column, $value ) = @_; + my $fs_file = $self->_file_column_file($column, $value); -=head2 _file_column_callback ($file,$ret,$target) + return { handle => $fs_file->open('r'), filename => $value }; +} -method made to be overridden for callback purposes. +sub _save_file_column { + my ( $self, $column, $value ) = @_; -=cut + return unless ref $value; + + my $fs_file = $self->_file_column_file($column, $value->{filename}); + mkpath [$fs_file->dir]; -sub _file_column_callback { - my ($self,$file,$ret,$target) = @_; + # File::Copy doesn't like Path::Class (or any for that matter) objects, + # thus ->stringify (http://rt.perl.org/rt3/Public/Bug/Display.html?id=59650) + File::Copy::copy($value->{handle}, $fs_file->stringify); + + $self->_file_column_callback($value, $self, $column); + + return $value->{filename}; } =head1 NAME DBIx::Class::InflateColumn::File - map files from the Database to the filesystem. -=head1 DESCRIPTION - -InflateColumn::File - =head1 SYNOPSIS In your L table class: __PACKAGE__->load_components( "PK::Auto", "InflateColumn::File", "Core" ); - + # define your columns __PACKAGE__->add_columns( "id", @@ -159,11 +136,12 @@ In your L table class: size => 255, }, ); - + In your L class: -FileColumn requires a hash that contains L as handle and the file's name as name. +FileColumn requires a hash that contains L as handle and the file's +name as name. my $entry = $c->model('MyAppDB::Articles')->create({ subject => 'blah', @@ -174,18 +152,33 @@ FileColumn requires a hash that contains L as handle and the file's na body => '....' }); $c->stash->{entry}=$entry; - + And Place the following in your TT template - + Article Subject: [% entry.subject %] Uploaded File: File Body: [% entry.body %] - -The file will be stored on the filesystem for later retrieval. -Calling delete on your resultset will delete the file from the filesystem. -Retrevial of the record automatically inflates the column back to the set hash with the IO::File handle and filename. + +The file will be stored on the filesystem for later retrieval. Calling delete +on your resultset will delete the file from the filesystem. Retrevial of the +record automatically inflates the column back to the set hash with the +IO::File handle and filename. + +=head1 DESCRIPTION + +InflateColumn::File + +=head1 METHODS + +=head2 _file_column_callback ($file,$ret,$target) + +method made to be overridden for callback purposes. + +=cut + +sub _file_column_callback {} =head1 AUTHOR