view Lib/IMPL/Web/DOM/FileNode.pm @ 245:7c517134c42f

Added Unsupported media type Web exception corrected resourceLocation setting in the resource Implemented localizable resources for text messages fixed TT view scopings, INIT block in controls now sets globals correctly.
author sergey
date Mon, 29 Oct 2012 03:15:22 +0400
parents 4d0e1962161c
children
line wrap: on
line source

package IMPL::Web::DOM::FileNode;
use parent qw(IMPL::DOM::Node);

__PACKAGE__->PassThroughArgs;

use IMPL::Class::Property;
use File::Temp qw(tempfile);

BEGIN {
    public property parameterName => {
        get => sub {
            my ($this) = @_;
            $this->_parameterName() or
            $this->_parameterName(
                join '/', ( map {
                    (defined $_->nodeProperty('instanceId')) ?
                        $_->nodeName . '['.$_->nodeProperty('instanceId').']':
                        $_->nodeName
                } $this->_selectParents, $this )
            );
        }
    };
    private property _parameterName => prop_all;
    public property fileName => {
        get => sub {
            my ($this) = @_;
            return $this->document->query->param($this->parameterName);
        }
    };
    public property fileHandle => {
        get => sub {
            my ($this) = @_;
            return $this->document->query->upload($this->parameterName);
        }
    };
}

sub invokeTempFile {
    my ($this,$sub,$target) = @_;
    
    die new IMPL::InvalidArgumentException("A reference to a function should be specified") unless $sub && ref $sub eq 'CODE';
    
    $target ||= $this;
    
    my $query = $this->document->nodeProperty('query') or die new IMPL::InvalidOperationException("Failed to get a CGI query from the document");
    my $hFile = $query->upload($this->parameterName) or die new IMPL::IOException("Failed to open the uploaded file",$query->cgi_error,$this->parameterName,$this->nodeProperty('instanceId'));
            
    my ($hTemp,$tempFileName) = tempfile();
    binmode($hTemp);
    
    print $hTemp $_ while <$hFile>;
    
    $hTemp->flush();
    seek $hTemp, 0,0;
    {
        local $_ = $tempFileName;
        $sub->($this,$tempFileName,$hTemp);
    }
}

sub _selectParents {
    my ($node) = @_;
    
    my @result;
    
    unshift @result, $node while $node = $node->parentNode;
    
    return @result;
}

1;

__END__

=pod

=head1 NAME

C<IMPL::Web::DOM::FileNode> - узел, использующийся для представления параметра запроса в котором передан файл.

=head1 SINOPSYS

=begin code xml

<!-- input.schema.xml -->
<schema>
    <SimpleType type="file" nativeType="IMPL::Web::DOM::FileNode"/>
    <ComplexNode name="user">
        <Node type="file" name="avatar"/>
    </ComplexNode>
</schema>

=end code xml

=begin code

# handle.pl
use IMPL::DOM::Transform::PostToDOM ();
use IMPL::DOM::Schema;
use CGI;
use File::Copy qw(copy);

my $t = new IMPL::DOM::Transform::PostToDOM(
    undef,
    IMPL::DOM::Schema->LoadSchema('input.schema.xml'),
    'user'    
);

my $doc = $t->Transform(CGI->new());

if ($t->Errors->Count) {
    # handle errors    
}

$doc->selectSingleNode('avatar')->invokeTempFile(
    sub {
        my($node,$fname,$fhandle) = @_;
        
        # do smth with file
        copy($_,'avatar.jpg');
        
        # same thing
        # copy($fname,'avatar.jpg');
    }
);

=end code

=head1 DESCRIPTION

Данный класс используется для представлении параметров C<CGI> запросов при преобзаовании
запроса в ДОМ документ преобразованием C<IMPL::DOM::Transform::PostToDOM>.

Узлы данного типа расширяют стандатрный C<IMPL::DOM::Node> несколькими свойствами и
методами для доступа к файлу, переданному в виде параметра запроса.

=head1 MEMBERS

=head2 PROPERTIES

=over

=item C<[get] parameterName>

Имя параметра C<CGI> запроса соответствующего данному узлу.

=item C<[get] fileName>

Имя файла из параметра запроса

=item C<[get] fileHandle>

Указатель на файл из параметра запроса

=back

=head2 METHODS

=over

=item C<invokeTempFile($callback,$target)>

Сохраняет файл, переданный в запросе во временный, вызывает C<$callback> для обработки временного файла.

=over

=item C<$callback>

Ссылка на функцию которая будет вызвана для обработки временного файла. C<callback($target,$fname,$fhandle)>

=over

=item C<$fname>

Имя временного файла

=item C<$fhandle>

Указатель на временный файл

=back
    
Также пременная C<$_> содержит имя временного файла.

=item C<$target>

Значение этого параметра будет передано первым параметром функции C<$callback>.

=back

=back

=cut