view Lib/IMPL/Web/DOM/FileNode.pm @ 178:658a80d19d33

new constructor syntax
author sourcer
date Wed, 12 Oct 2011 00:06:07 +0300
parents 1f7a6d762394
children d1676be8afcc
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