changeset 100:df6b4f054957

Schema in progress Added simple mailer
author wizard
date Thu, 06 May 2010 00:54:17 +0400
parents 6dd659f6f66c
children d8dc6cad3f55
files Lib/IMPL/DOM/Schema.pm Lib/IMPL/DOM/Schema/Node.pm Lib/IMPL/DOM/Schema/NodeList.pm Lib/IMPL/DOM/Schema/NodeSet.pm Lib/IMPL/DOM/Schema/ValidationError.pm Lib/IMPL/DOM/Schema/Validator.pm Lib/IMPL/DOM/Schema/Validator/RegExp.pm Lib/IMPL/Mailer.pm _test/Resources/form.xml _test/Resources/types.xml
diffstat 10 files changed, 159 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/Lib/IMPL/DOM/Schema.pm	Wed May 05 17:33:55 2010 +0400
+++ b/Lib/IMPL/DOM/Schema.pm	Thu May 06 00:54:17 2010 +0400
@@ -34,7 +34,7 @@
 sub Create {
     my ($this,$nodeName,$class,$refArgs) = @_;
     
-    die new IMPL::Exception('Invalid node class') unless $class->isa('IMPL::DOM::Schema::Node');
+    die new IMPL::Exception('Invalid node class') unless $class->isa('IMPL::DOM::Node');
     
     goto &SUPER::Create;
 }
@@ -138,8 +138,7 @@
         IMPL::DOM::Schema::ComplexType->new(type => 'Validator', nativeType => 'IMPL::DOM::Schema::Validator')->appendRange(
             IMPL::DOM::Schema::NodeList->new()->appendRange(
                 IMPL::DOM::Schema::AnyNode->new(maxOccur => 'unbounded', minOccur => 0)
-            ),
-            new IMPL::DOM::Schema::Property(name => 'name')
+            )
         )
     );
     
@@ -181,7 +180,7 @@
 
 =head1 META SCHEMA
 
-Схема для описания схемы, эта схема используется для постороения других схем
+Схема для описания схемы, эта схема используется для постороения других схем, выглядит приблизительно так
 
 =begin code xml
 
--- a/Lib/IMPL/DOM/Schema/Node.pm	Wed May 05 17:33:55 2010 +0400
+++ b/Lib/IMPL/DOM/Schema/Node.pm	Thu May 06 00:54:17 2010 +0400
@@ -12,6 +12,9 @@
     public _direct property maxOccur => prop_all;
     public _direct property type => prop_all;
     public _direct property name => prop_all;
+    public _direct property display => prop_all;
+    public _direct property display_no => prop_all;
+    public _direct property display_blame => prop_all;
 }
 
 our %CTOR = (
@@ -25,6 +28,9 @@
     $this->{$maxOccur} = defined $args{maxOccur} ? $args{maxOccur} : 1;
     $this->{$type} = $args{type};
     $this->{$name} = $args{name} or die new IMPL::InvalidArgumentException('Argument is required','name');
+    $this->{$display} = $args{display};
+    $this->{$display_no} = $args{display_no};
+    $this->{$display_blame} = $args{display_blame};
 }
 
 sub Validate {
--- a/Lib/IMPL/DOM/Schema/NodeList.pm	Wed May 05 17:33:55 2010 +0400
+++ b/Lib/IMPL/DOM/Schema/NodeList.pm	Thu May 06 00:54:17 2010 +0400
@@ -80,7 +80,6 @@
         return new IMPL::DOM::Schema::ValidationError (
             Error => 1,
             Message => $this->messageNodesRequired,
-            Node => $node,
             Source => $this,
             Schema => $info->{Schema}
         ) if $info->{Seen} < $info->{Min};
--- a/Lib/IMPL/DOM/Schema/NodeSet.pm	Wed May 05 17:33:55 2010 +0400
+++ b/Lib/IMPL/DOM/Schema/NodeSet.pm	Thu May 06 00:54:17 2010 +0400
@@ -55,7 +55,6 @@
             push @errors, new IMPL::DOM::Schema::ValidationError (
                 Source => $this,
                 Node => $child,
-                Schema => $info->{Schema},
                 Message => $this->messageUnexpected
             )
         }
@@ -65,7 +64,6 @@
         push @errors, new IMPL::DOM::Schema::ValidationError (
             Source => $this,
             Schema => $info->{Schema},
-            Node => $node,
             Message => $this->messageMin
         ) if $info->{Min} > $info->{Seen};
     }
--- a/Lib/IMPL/DOM/Schema/ValidationError.pm	Wed May 05 17:33:55 2010 +0400
+++ b/Lib/IMPL/DOM/Schema/ValidationError.pm	Thu May 06 00:54:17 2010 +0400
@@ -17,7 +17,7 @@
 sub CTOR {
     my ($this,%args) = @_;
     
-    $this->{$Node} = $args{Node} or die new IMPL::InvalidArgumentException("Node is a required parameter");
+    $this->{$Node} = $args{Node};
     $this->{$Schema} = $args{Schema} if $args{Schema};
     $this->{$Source} = $args{Source} if $args{Source};
     $this->{$Message} = FormatMessage(delete $args{Message}, \%args) if $args{Message};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Lib/IMPL/DOM/Schema/Validator.pm	Thu May 06 00:54:17 2010 +0400
@@ -0,0 +1,29 @@
+package IMPL::DOM::Schema::Validator;
+
+use base qw(IMPL::DOM::Node);
+
+require IMPL::Exception;
+
+__PACKAGE__->PassThroughArgs;
+
+sub Validate {
+	my ($this,$node) = @_;
+	
+	die new IMPL::NotImplementedException();
+}
+
+1;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+C<IMPL::DOM::Schema::Validator> - Базовый класс для ограничений на простые значения.
+
+=head1 DESCRIPTION
+От основных элементов схемы его отличает то, что в конечном документе он не соответсвует
+никаким узлам и поэтому у него отсутствуют свойства C<minOcuur,maxOccur,name>.
+
+=cut
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Lib/IMPL/DOM/Schema/Validator/RegExp.pm	Thu May 06 00:54:17 2010 +0400
@@ -0,0 +1,37 @@
+package IMPL::DOM::Schema::Validator::RegExp;
+
+use base qw(IMPL::DOM::Schema::Validator);
+
+our %CTOR = (
+	'IMPL::DOM::Schema::Validator' => sub {
+		my %args = @_;
+		$args{nodeName} ||= 'RegExp';
+		%args;
+	}
+);
+
+use IMPL::Class::Property;
+
+BEGIN {
+	public property message => prop_all;
+}
+
+sub CTOR {
+	my ($this) = @_;
+	
+	$this->message("A %Node.nodeName% doesn't match to the format %Schema.name%");
+}
+
+sub Validate {
+	my ($this,$node) = @_;
+	
+	my $rx = $this->nodeValue;
+	return new IMPL::DOM::Schema::ValidationError(
+		Node => $node,
+		Source => $this,
+		Schema => $this->parentNode,
+		Message => $this->message
+	) unless (not $node->isComplex) and $node->nodeValue =~ /$rx/;
+}
+
+1;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Lib/IMPL/Mailer.pm	Thu May 06 00:54:17 2010 +0400
@@ -0,0 +1,69 @@
+package IMPL::Mailer;
+use strict;
+
+use Encode qw (encode);
+use Encode::MIME::Header;
+use MIME::Base64 qw(encode_base64);
+use Email::Simple;
+
+our $SENDMAIL;
+
+sub DeliverMessage {
+    my $message = shift;
+    
+    $message = shift if $message eq __PACKAGE__ or ref $message eq __PACKAGE__;
+    
+    my $email = new Email::Simple($message);
+    
+    $email->header_set('Content-Transfer-Encoding' => 'base64');
+    $email->header_set('MIME-Version' => '1.0') if !$email->header('MIME-Version');
+    $email->header_set('Content-Type' => 'text/plain; charset="utf-8"');
+    my $raw = $email->body();
+    utf8::encode($raw) if utf8::is_utf8($raw);
+    $email->body_set(encode_base64($raw));
+    
+    foreach my $field ($email->header_names()) {
+        $email->header_set($field, map { encode('MIME-Header', utf8::is_utf8($_) ? $_ : Encode::decode('utf-8',$_) ) } $email->header($field) );
+    }
+    
+    return SendMail($email,@_);
+}
+
+sub _find_sendmail {
+    return $SENDMAIL if defined $SENDMAIL;
+
+    my @path = split /:/, $ENV{PATH};
+    my $sendmail;
+    for (@path) {
+        if ( -x "$_/sendmail" ) {
+            $sendmail = "$_/sendmail";
+            last;
+        }
+    }
+    return $sendmail;
+}
+
+sub SendMail {
+    my ($message, %args) = @_;
+    my $mailer = _find_sendmail;
+    
+    local *SENDMAIL;
+    if( $args{'TestFile'} ) {
+        open SENDMAIL, '>', $args{TestFile} or die "Failed to open $args{TestFile}: $!";
+        binmode(SENDMAIL);
+        print SENDMAIL "X-SendMail-Cmd: sendmail ",join(' ',%args),"\n";
+    } else {
+        my @args = %args;
+        die "sendmail not found" unless $mailer;
+        die "Found $mailer but cannot execute it"
+        unless -x $mailer;
+        open SENDMAIL, "| $mailer -t -oi @args"
+            or die "Error executing $mailer: $!";
+    }
+    print SENDMAIL $message->as_string
+        or die "Error printing via pipe to $mailer: $!";
+    close SENDMAIL;
+    return 1;
+}
+
+1;
--- a/_test/Resources/form.xml	Wed May 05 17:33:55 2010 +0400
+++ b/_test/Resources/form.xml	Thu May 06 00:54:17 2010 +0400
@@ -2,13 +2,17 @@
 <schema>
 	<Include source="types.xml"/>
     <ComplexNode name="user">
-    	<NodeSet>
-    		<Node name="name" type="scalar"/>
-    		<Node name="email" type="email"/>
-    		<Node name="fullName" type="scalar"/>
-    		<Node name="birthDate" type="date"/>
-    		<Node name="gender" type="scalar"/>
-    		<Node name="region" type="region"/>
+    	<NodeSet
+    		messageMin="треюуется указать %Schema.display_blame%"
+    		messageMax="%Schema.display% не может встречаться более %Schema.maxOccur% раз"
+    		messageUnexpected="неизвестный параметр %Node.nodeName%"
+    	>
+    		<Node name="name" type="scalar" display="РёРјСЏ" display_blame="РёРјСЏ"/>
+    		<Node name="email" type="email" display="электронная почта" display_blame="электронную почту" />
+    		<Node name="fullName" type="scalar" display="полное имя" diplay_blame="полное имя"/>
+    		<Node name="birthDate" type="date" display="дата рождения" display_blame="дату рождения"/>
+    		<Node name="gender" type="scalar" display="РїРѕР»" display_blame="РїРѕР»"/>
+    		<Node name="region" type="region" display="ваш регион" display_blame="ваш регион"/>
     	</NodeSet>
     </ComplexNode>
 </schema>
--- a/_test/Resources/types.xml	Wed May 05 17:33:55 2010 +0400
+++ b/_test/Resources/types.xml	Thu May 06 00:54:17 2010 +0400
@@ -1,5 +1,7 @@
 <schema>
-	<SimpleType name="email" nativeType="SCALAR"/>
+	<SimpleType type="email" nativeType="SCALAR">
+		<RegExp message="Неверный формат %Node.name_no%">^\w+(\.\w+)*@$\w+(\.\w+)+</RegExp>
+	</SimpleType>
 	<SimpleType name="scalar" nativeType="SCALAR"/>
 	<SimpleType name="date" nativeType="DateTime"/>
 </schema>
\ No newline at end of file