diff lib/IMPL/Web/DOM/FileNode.pm @ 407:c6e90e02dd17 ref20150831

renamed Lib->lib
author cin
date Fri, 04 Sep 2015 19:40:23 +0300
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/IMPL/Web/DOM/FileNode.pm	Fri Sep 04 19:40:23 2015 +0300
@@ -0,0 +1,193 @@
+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