package Template; use strict; use JFile; use CSV; sub new { my ($module, @a) = @_; my $this = {}; bless $this; for(my $i = 0 ; $i < @a ; $i += 2) { my $key = $a[$i]; my $val = $a[$i+1]; $key =~ s/^-//; $this->{$key} = $val; } return $this; } sub InvalidateBraKet { my ($str, $bra, $ket) = @_; $bra = '{' if(!defined $bra); $ket = '}' if(!defined $ket); my $bracode = Utils::ChrToHTMLCode($bra); my $ketcode = Utils::ChrToHTMLCode($ket); $str =~ s/$bra/$bracode/gsi; $str =~ s/$ket/$ketcode/gsi; return $str; } sub ReadExcelTemplate { my ($this, $TemplatePath, $key) = @_; return $this->ReadHTMLTemplate($TemplatePath, $key); } sub ReadHTMLTemplate { my ($this, $TemplatePath, $key) = @_; $key = "\\{sn\\}" if(!defined $key); $this->{TemplatePath} = $TemplatePath if(defined $TemplatePath); my $content = JFile->new()->ReadFile($TemplatePath, undef, "r"); return undef if(!$content); my ($head, $template, $tail) = ('', '', $content); while(1) { my ($s1, $s2, $s3) = ($tail =~ /^(.*?)()(.*)$/si); last if(!defined $s1); if($s2 =~ /$key/) { $template = $s2; $head .= $s1; $tail = $s3; last } else { $head .= $s1 . $s2; $tail = $s3; } } $head =~ s/(.*?)<\/span>/$1/sg; $template =~ s/(.*?)<\/span>/$1/sg; $tail =~ s/(.*?)<\/span>/$1/sg; $head =~ s/%7B/{/i; $head =~ s/%7D/}/i; $template =~ s/%7B/{/i; $template =~ s/%7D/}/i; $tail =~ s/%7B/{/i; $tail =~ s/%7D/}/i; #print "h [$head]
\n"; return ($head, $template, $tail); } sub ReadCSVTemplate { my ($this, $TemplatePath, $key) = @_; $key = "\\{sn\\}" if(!defined $key); $this->{TemplatePath} = $TemplatePath if(defined $TemplatePath); my $content = JFile->new()->ReadFile($TemplatePath, undef, "r"); return undef if(!$content); my ($head, $template, $tail) = ('', '', $content); while(1) { my ($s1, $s2, $s3) = ($tail =~ /^(.*?)(.*?[\r\n]+)(.*)$/si); last if(!defined $s1); if($s2 =~ /$key/) { $template = $s2; $head .= $s1; $tail = $s3; last } else { $head .= $s1 . $s2; $tail = $s3; } } return ($head, $template, $tail); } sub ReadTemplate { my ($this, $TemplatePath, $LineKey) = @_; $this->{TemplatePath} = $TemplatePath if(defined $TemplatePath); $LineKey = $this->{LineKey} if(!defined $LineKey); $this->{Template} = JFile->new()->ReadFile($this->{TemplatePath}) or return undef; # に{:Start}タグがあり、それによって背景の表示がページごとにうまくいっている # $this->{Template} =~ s/\<title[^\>]*?\>.*?\<\/title[^\>]*?\>//; my ($nRepeat, $pNumbered, $pNonNumbered) = $this->ParseTemplate($this->{Template}); if(defined $this->{Type} and $this->{Type} eq 'HTML') { ($this->{TemplateHeader}, $this->{TemplatePage}, $this->{TemplateTail}) = $this->ReadHTMLTemplate($this->{TemplatePath}, $LineKey); } elsif(defined $this->{Type} and $this->{Type} eq 'CSV') { ($this->{TemplateHeader}, $this->{TemplatePage}, $this->{TemplateTail}) = $this->ReadCSVTemplate($this->{TemplatePath}, $LineKey); } elsif(defined $this->{Type} and $this->{Type} eq 'Excel') { ($this->{TemplateHeader}, $this->{TemplatePage}, $this->{TemplateTail}) = $this->ReadExcelTemplate($this->{TemplatePath}, $LineKey); } else { my $KeyPageStart = $this->{KeyPageStart}; my $KeyPageEnd = $this->{KeyPageEnd}; if(defined $KeyPageStart and defined $KeyPageEnd) { ($this->{TemplateHeader}, $this->{TemplatePage}, $this->{TemplateTail}) = ($this->{Template} =~ /^(.*?)$KeyPageStart(.*)$KeyPageEnd(.*?)$/si); } } if($this->{DeleteHeader}) { $this->{TemplateHeader} =~ s/^.*\<\s*body[^\>]*\>\s*//si; $this->{TemplateTail} =~ s/\s*\<\/\s*body[^\>]*\>.*$//si; } if($this->{CharCode} ne '') { Jcode::convert(\$this->{TemplateHeader}, $this->{CharCode}); Jcode::convert(\$this->{TemplatePage}, $this->{CharCode}); Jcode::convert(\$this->{TemplateTail}, $this->{CharCode}); } $this->{nRepeat} = $nRepeat if(!defined $this->{nRepeat}); #print "nRepeat=$nRepeat<br>\n"; return $this->{Template}; } sub ParseTemplate { my ($this, $text) = @_; $text = $this->{Template} if(!defined $text); #print "text: [$text]\n"; my @a = ($text =~ /{[\w\d]+?}/g); my (%Numbered, %NonNumbered); my $nMaxIndex = 0; foreach my $s (@a) { #print "$s\n"; if($s =~ /^\{(.+?)(\d+)\}$/) { my $key = $1; my $i = $2; $nMaxIndex = $i if($i > $nMaxIndex); $Numbered{$key}++; } else { $NonNumbered{$s}++; } } if(0) { print "nMaxIndex: $nMaxIndex<br>\n"; foreach my $key (keys %Numbered) { print "Nubmered: $key<br>\n"; } foreach my $key (keys %NonNumbered) { print "NonNubmered: $key<br>\n"; } } $nMaxIndex = $this->{nRepeat} if(defined $this->{nRepeat}); return ($nMaxIndex, [keys %Numbered], [keys %NonNumbered]); } sub ReadIndex { my ($this) = @_; $this->{IndexCSV} = new CSV; $this->{IndexCSV}->Read($this->{IndexPath}, 0, 0) or return undef; return $this->{IndexCSV}; } sub ReplaceByHash { my ($this, $text, $pHash, $bra, $ket, $ExtractHTMLBody, $CharCode, $ShowError, $InvalidateHTMLTags, $RemoveUndefined, $ReplaceRegExp) = @_; #print "<H1>$ket, $ExtractHTMLBody, $CharCode, $ShowError, $InvalidateHTMLTags, $RemoveUndefined, $ReplaceRegExp</H1>\n"; $InvalidateHTMLTags = 0 if(!defined $InvalidateHTMLTags); $RemoveUndefined = 1 if(!defined $RemoveUndefined); $ReplaceRegExp = 0 if(!defined $ReplaceRegExp); if($ExtractHTMLBody) { ($text) = ($text =~ /<body[^>]*>(.*)<\/body[^>]*>/si); } $CharCode = 'utf8' if($CharCode =~ /utf-8/i); my $Convert = ($CharCode =~ /(jp|jis|utf)/i)? 1 : 0; if($Convert) { Jcode::convert(\$text, $CharCode); } #print("LogonMessage[$pHash->{LogonMessage_jp}]<br>\n"); foreach my $key (sort keys %$pHash) { # foreach my $key (sort { length($a) <=> length($b); } keys %$pHash) { my $val = $pHash->{$key}; $val =~ s/$bra/_br$bra\_/sg; $val =~ s/$ket/_br$ket\_/sg; #$val =~ s/${bra}/_br${bra}_/sg; #$val =~ s/${ket}/_br${ket}_/sg; #print "$key<br>\n"; #print "<b>$key:</b> $val<br>\n"; if($Convert) { Jcode::convert(\$val, $CharCode); } Utils::InvalidateHTMLTags($val) if($InvalidateHTMLTags); $key = Utils::RegExpQuote($key); #$val = Utils::URLDecode($val); if($key =~ /^\d/) { $text =~ s/\\$bra$key\\$ket/$val/sg; } else { $text =~ s/$bra$key$ket/$val/sg; } } if($RemoveUndefined and defined $bra and defined $ket) { $text =~ s/$bra[\$_\w]+$ket//sg; } $bra =~ s/\{/\\{/g; $ket =~ s/\}/\\}/g; $text =~ s/_br$bra\_/$bra/sg; $text =~ s/_br$ket\_/$ket/sg; #$text =~ s/_br${bra}_/$bra/sg; #$text =~ s/_br${ket}_/$ket/sg; #print "val: $text<br>\n"; if($ReplaceRegExp) { $text =~ s/\\\\/\\/g; $text =~ s/\\'/'/g; $text =~ s/\\"/"/g; $text =~ s/\\\?/\?/g; $text =~ s/\\n/\n/g; $text =~ s/\\r/\r/g; $text =~ s/\\t/\t/g; $text =~ s/\\</\</g; $text =~ s/\\>/\>/g; } #print "t[$text]\n"; return $text; } sub GetTextByHash { my ($this, $TemplatePath, $pHash, $bra, $ket, $ExtractHTMLBody, $CharCode, $ShowError, $InvalidateHTMLTags, $RemoveUndefined, $ReplaceRegExp) = @_; #Utils::InitHTML(); #print "cc: [$CharCode]<br>\n"; my $text = $this->ReadTemplate($TemplatePath); #print "cc2: [$CharCode]<br>\n"; if($ShowError and !defined $text) { print "Error in Template::GetTextByHash: Can not read [$TemplatePath].\n"; return undef; } #print "cc3: [$CharCode]<br>\n"; #print "aa [$pHash][$TemplatePath]<br>"; $text = $this->ReplaceByHash($text, $pHash, $bra, $ket, $ExtractHTMLBody, $CharCode, $ShowError, $InvalidateHTMLTags, $RemoveUndefined, $ReplaceRegExp); #my $text2 = Utils::InvalidateHTMLTags($text); #print "cc4: [$CharCode]<br><br>[$text2]<br><br>\n"; return $text; } sub SaveTo { my ($this, $OutputPath, $pConvertCallbackFunc) = @_; my $out = new JFile($OutputPath, "w") or return undef; my $ret = $this->SaveToWithOutputHandle($out, $pConvertCallbackFunc); $out->Close(); return $ret; } sub SaveToWithOutputHandle { my ($this, $out, $pConvertCallbackFunc, $pDefaultReplaceHash) = @_; #print "cf: $pConvertCallbackFunc<br>\n"; if(!defined $this->{Template}) { $this->ReadTemplate() or return undef; } if(defined $this->{IndexPath} and !defined $this->{IndexCSV}) { $this->ReadIndex() or return undef; } my $nRepeat = $this->{nRepeat}; $nRepeat = 1 if($nRepeat == 0); my $TemplateHeader = $this->{TemplateHeader}; my $TemplatePage = $this->{TemplatePage}; my $TemplateTail = $this->{TemplateTail}; my $KeyPageStart = $this->{KeyPageStart}; my $KeyPageEnd = $this->{KeyPageEnd}; #print "h [", Utils::InvalidateHTMLTags($TemplateHeader), "]<br>\n"; #print "p [", Utils::InvalidateHTMLTags($TemplatePage), "]<br>\n"; #print "t [", Utils::InvalidateHTMLTags($TemplateTail), "]<br>\n"; my $csv = $this->{IndexCSV}; # my $nArray = $csv->nDataArray(); my $nData; if($csv) { $nData = $csv->nData(); } else { $nData = $this->{pDatabase}->nHit(); } #print("$nData found (nRepeat=$nRepeat).<br>\n"); #print "header [$TemplateHeader]<br>\n"; #print "template body [$TemplatePage]<br>\n"; #print "tail [$TemplateTail]<br>\n"; Utils::ConvertString($TemplateHeader, "{%key%}", %$pDefaultReplaceHash); $out->print($TemplateHeader); my $count = 0; for(my $i = 0 ; $i < $nData ; ) { my %ReplaceHash; #print "i=$i,$nRepeat<br>\n"; my $DoOutput = 0; for(my $j = 0 ; $j < $nRepeat ; ) { my $pHash; #print "i=$i,$j,$count [$nData]<br>\n"; last if($count >= $nData); if($csv) { $pHash = $csv->GetHashData($count); } else { %$pHash = $this->{pDatabase}->GetNextHit(); } $count++; #foreach my $key (keys %$pHash) { # $out->print("$key: $pHash->{$key}\n"); #} if($pConvertCallbackFunc) { if(&$pConvertCallbackFunc($this, $pHash, $this->{CharCode})) { $DoOutput = 1; #print("<H3>Fee[$pHash->{RegistrationFee}]</H3>\n"); } else { next; } } else { $DoOutput = 1; } if($j == 0) { foreach my $key (keys %$pHash) { #print("<H3>Fee2[$pHash->{RegistrationFee}]</H3>\n") if($key eq 'RegistrationFee'); $ReplaceHash{$key} = $pHash->{$key}; } } my $j1 = $j + 1; foreach my $key (keys %$pHash) { #print("<H3>Fee2[$pHash->{RegistrationFee}]</H3>\n") if($key eq 'RegistrationFee'); $ReplaceHash{"${key}$j1"} = $pHash->{$key}; } $j++; $i++; } if($DoOutput) { my $s = $TemplatePage; Utils::ConvertString($s, "{%key%}", %ReplaceHash); # ファイル先頭に{:Start}タグを書くと、<title>にも同じタグが入り、それによって背景の表示がページごとにうまくいっている # ただし{:Start}タグが本文にでもでてくるので、それを削除する $s =~ s/$KeyPageStart//g if($KeyPageStart ne ''); #$s =~ s/$KeyPageEnd//g; #print "bb [$s]<br>\n"; $out->print($s); } last if($count >= $nData); } #print "t [$TemplateTail]<br>\n"; Utils::ConvertString($TemplateTail, "{%key%}", %$pDefaultReplaceHash); $out->print($TemplateTail); return 1; } 1;