⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 builder.pm

📁 1. 记录每个帖子的访问人情况
💻 PM
字号:
# Copyright 2001-2005 Six Apart.# SCRiPTMAFiA 2005 - THE DiRTY HANDS ON YOUR SCRiPTS## $Id: Builder.pm 10197 2005-03-09 00:27:57Z ezra $package MT::Builder;use strict;use MT::ErrorHandler;@MT::Builder::ISA = qw( MT::ErrorHandler );sub new { bless { }, $_[0] }# use Time::HiRes;# my @tag_stack = ('toplevel');# my @timer_stack = ( [ Time::HiRes::time(), 0 ] );# my $totaltime = 0;sub compile {    my $build = shift;    my($ctx, $text) = @_;    return [ ] unless $text;    my $state = local $build->{__state} = { tokens => [ ] };    $state->{text} = \$text;    my $pos = 0;    my $len = length $text;    while ($text =~ m!(<\$?MT(.+?)[\$/]?>)!gs) {        my($whole_tag, $tag) = ($1, $2);        ($tag, my($args)) = split /\s+/, $tag, 2;        my $sec_start = pos $text;        my $tag_start = $sec_start - length $whole_tag;        _text_block($state, $pos, $tag_start) if $pos < $tag_start;        $args ||= '';        my %args;        while ($args =~ /(\w+)\s*=\s*(["'])(.*?)\2/gs) { #"            $args{$1} = $3;        }        my($h, $is_container) = $ctx->handler_for($tag);        my $rec = [ $tag, \%args ];        if ($is_container) {            if ($whole_tag !~ m|/>|) {                my ($sec_end, $tag_end) = _consume_up_to(\$text,$sec_start,$tag);                if ($sec_end) {                    my $sec = substr $text, $sec_start, $sec_end - $sec_start;                    $sec =~ s!^\n!!;                    $rec->[2] = $build->compile($ctx, $sec) or return;                    $rec->[3] = $sec;                } else {                    return $build->error("&lt;MT$tag> with no &lt;/MT$tag>");                }                $pos = $tag_end + 1;                (pos $text) = $tag_end;            } else {                $rec->[3] = '';                $pos = pos $text;            }        } else {            $pos = pos $text;        }        push @{ $state->{tokens} }, $rec;        $pos = pos $text;    }    _text_block($state, $pos, $len) if $pos < $len;    $state->{tokens};}sub _consume_up_to {    my($text, $start, $stoptag) = @_;    my $pos;    (pos $$text) = $start;    while ($$text =~ m!(<([\$/]?)MT($stoptag[^>]*?)[\$/]?>)!g) {        my($whole_tag, $prefix, $tag) = ($1, $2, $3);        ($tag, my($args)) = split /\s+/, $tag, 2;        next if $tag ne $stoptag;        my $end = pos $$text;        if ($prefix && ($prefix eq '/')) {            return ($end - length($whole_tag), $end);        } elsif ($whole_tag !~ m|/>|) {            my ($sec_end, $end_tag) = _consume_up_to($text, $end, $tag);            last if !$sec_end;            (pos $$text) = $end_tag;        }    }    return (0, 0);}sub _text_block {    my $text = substr ${ $_[0]->{text} }, $_[1], $_[2] - $_[1];    push @{ $_[0]->{tokens} }, [ 'TEXT', $text ] if $text;}sub build {    my $build = shift;    my($ctx, $tokens, $cond) = @_;    $cond ||= { };    $ctx->stash('builder', $build);    my $res = '';    my $ph = $ctx->post_process_handler;    for my $t (@$tokens) {        if ($t->[0] eq 'TEXT') {            $res .= $t->[1];        } else {            my($tokens, $tokens_else, $uncompiled);            if (exists $cond->{ $t->[0] } && !$cond->{ $t->[0] }) {		# if there's a cond for this tag and it's false,		# walk the children and look for an MTElse.		# the children of the MTElse will become $tokens                for my $tok (@{ $t->[2] }) {                    if ($tok->[0] eq 'Else') {                        $tokens = $tok->[2];                        $uncompiled = $tok->[3];                        last;                    }                }                next unless $tokens;            } else {                if ($t->[2] && ref($t->[2]) eq 'ARRAY') {		    # either there is no cond for this tag, or it's true,		    # so we want to partition the children into		    # those which are inside an else and those which are not.                    ($tokens, $tokens_else) = ([], []);                    for my $sub (@{ $t->[2] }) {                        if ($sub->[0] eq 'Else') {                            push @$tokens_else, $sub;                        } else {                            push @$tokens, $sub;                        }                    }                }                $uncompiled = $t->[3];            }            my($h) = $ctx->handler_for($t->[0]);            if ($h) {                local($ctx->{__stash}->{tag}) = $t->[0];                local($ctx->{__stash}->{tokens}) = $tokens;                local($ctx->{__stash}->{tokens_else}) = $tokens_else;	        local($ctx->{__stash}->{uncompiled}) = $uncompiled;                local($t->[1]) = $t->[1];                my $out = $h->($ctx, $t->[1], $cond);                return $build->error("Error in <MT$t->[0]> tag: " .                                     $ctx->errstr) unless defined $out;                if ($ph) {                    $out = $ph->($ctx, $t->[1], $out);                }                $res .= $out;            }        }    }    $res;}1;__END__=head1 NAMEMT::Builder - Parser and interpreter for MT templates=head1 SYNOPSIS    use MT::Builder;    use MT::Template::Context;    my $build = MT::Builder->new;    my $ctx = MT::Template::Context->new;    my $tokens = $build->compile($ctx, '<$MTVersion$>')        or die $build->errstr;    defined(my $out = $build->build($ctx, $tokens))        or die $build->errstr;=head1 DESCRIPTIONI<MT::Builder> provides the parser and interpreter for taking a templatebody and turning it into a generated output page. An I<MT::Builder> objectknows how to parse a string of text into tokens, then take those tokens andbuild a scalar string representing the output of the page. It does not,however, know anything about the types of tags that it encounters; it handsoff this work to the I<MT::Template::Context> object, which can look up atag and determine whether it's valid, whether it's a container or substitutiontag, etc.All I<MT::Builder> knows is the basic structure of a Movable Type tag, andhow to break up a string into pieces: plain text pieces interspersed withtag callouts. It then knows how to take a list of these tokens/pieces andbuild a completed page, using the same I<MT::Template::Context> object toactually fill in the values for the Movable Type tags.=head1 USAGE=head2 MT::Builder->newConstructs and returns a new parser/interpreter object.=head2 $build->compile($ctx, $string)Given an I<MT::Template::Context> object I<$ctx>, breaks up the scalar stringI<$string> into tokens and returns the list of tokens as a reference to anarray. Returns C<undef> on compilation failure.=head2 $build->build($ctx, \@tokens [, \%cond ])Given an I<MT::Template::Context> object I<$ctx>, turns a list of tokensI<\@tokens> and generates an output page. Returns the output page on success,C<undef> on failure. Note that the empty string (C<''>) and the number zero(C<0>) are both valid return values for this method, so you should checkspecifically for an undefined value when checking for errors.The optional argument I<\%cond> specifies a list of conditions under whichthe tokens will be interpreted. If provided, I<\%cond> should be a referenceto a hash, where the keys are MT tag names (without the leading C<MT>), andthe values are boolean flags specifying whether to include the tag; a truevalue means that the tag should be included in the final output, a false valuethat it should not. This is useful when a template includes conditionalcontainer tags (eg C<E<lt>MTEntryIfExtendedE<gt>>), and you wish to influencethe inclusion of these container tags. For example, if a template containsthe container    <MTEntryIfExtended>    <$MTEntryMore$>    </MTEntryIfExtended>and you wish to exclude this conditional, you could call I<build> like this:    my $out = $build->build($ctx, $tokens, { EntryIfExtended => 0 });=head1 ERROR HANDLINGOn an error, the above methods return C<undef>, and the error message canbe obtained by calling the method I<errstr> on the object. For example:    defined(my $out = $build->build($ctx, $tokens))        or die $build->errstr;=head1 AUTHOR & COPYRIGHTSPlease see the I<MT> manpage for author, copyright, and license information.=cut

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -