Changeset 2973

Show
Ignore:
Timestamp:
08/25/08 23:05:34 (3 months ago)
Author:
bchoate
Message:

MT::Template::Node refactoring from Hirotaka-san. BugId:79926

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/lib/MT/Builder.pm

    r2212 r2973  
    99use strict; 
    1010use base qw( MT::ErrorHandler ); 
    11 use MT::Util qw( weaken )
     11use MT::Template::Node
    1212 
    1313sub NODE () { 'MT::Template::Node' } 
     
    8080        #   tag name, attribute hashref, contained tokens, template text, 
    8181        #       attributes arrayref, parent array reference 
    82         my $rec = bless [ $tag, \my %args, undef, undef, \my @args ], NODE
     82        my $rec = NODE->new(tag => $tag, attributes => \my %args, attribute_list => \my @args)
    8383        while ($args =~ / 
    8484            (?: 
     
    153153                            : substr $text, $sec_start, $sec_end - $sec_start; 
    154154                    if ($sec !~ m/<\$?MT/i) { 
    155                         $rec->[2] = [ ($sec ne '' ? ['TEXT', $sec ] : ()) ]
     155                        $rec->childNodes([ ($sec ne '' ? NODE->new(tag => 'TEXT', nodeValue => $sec) : ()) ])
    156156                    } 
    157157                    else { 
    158158                        local $opt->{depth} = $opt->{depth} + 1; 
    159159                        local $opt->{parent} = $rec; 
    160                         $rec->[2] = $build->compile($ctx, $sec, $opt); 
     160                        $rec->childNodes($build->compile($ctx, $sec, $opt)); 
    161161                        if ( @$errors ) { 
    162162                            my $pre_error = substr($text, 0, $sec_start); 
     
    185185                        # } 
    186186                    } 
    187                     $rec->[3] = $sec if $opt->{uncompiled}; 
     187                    $rec->nodeValue($sec) if $opt->{uncompiled}; 
    188188                } 
    189189                else { 
     
    206206            } 
    207207            else { 
    208                 $rec->[3] = ''
    209             } 
    210         } 
    211         weaken($rec->[5] = $opt->{parent} || $tmpl); 
    212         weaken($rec->[6] = $tmpl); 
     208                $rec->nodeValue('')
     209            } 
     210        } 
     211        $rec->parentNode($opt->{parent} || $tmpl); 
     212        $rec->template($tmpl); 
    213213        push @{ $state->{tokens} }, $rec; 
    214214        $pos = pos $text; 
     
    257257    my $text = substr ${ $_[0]->{text} }, $_[1], $_[2] - $_[1]; 
    258258    if ((defined $text) && ($text ne '')) { 
    259         my $rec = bless [ 'TEXT', $text, undef, undef, undef, $_[0]->{tokens}, $_[0]->{tmpl} ], NODE; 
    260         # Avoids circular reference between NODE and TOKENS, MT::Template. 
    261         weaken($rec->[5]); 
    262         weaken($rec->[6]); 
     259        my $rec = NODE->new(tag => 'TEXT', nodeValue => $text, parentNode => $_[0]->{tokens}, template => $_[0]->{tmpl}); 
    263260        push @{ $_[0]->{tokens} }, $rec; 
    264261    } 
     
    269266    my $string = ''; 
    270267    foreach my $t (@$tokens) { 
    271         my ($name, $args, $tokens, $uncompiled) = @$t
     268        my ($name, $args, $tokens, $uncompiled) = ($t->tag, $t->attributes, $t->childNodes, $t->nodeValue)
    272269        $string .= (" " x $depth) .  $name; 
    273270        if (ref $args eq 'HASH') { 
     
    305302 
    306303    for my $t (@$tokens) { 
    307         if ($t->[0] eq 'TEXT') { 
    308             $res .= $t->[1]
     304        if ($t->tag eq 'TEXT') { 
     305            $res .= $t->nodeValue
    309306        } else { 
    310307            my($tokens, $tokens_else, $uncompiled); 
    311             my $tag = lc $t->[0]
     308            my $tag = lc $t->tag
    312309            if ($cond && (exists $cond->{ $tag } && !$cond->{ $tag })) { 
    313310                # if there's a cond for this tag and it's false, 
    314311                # walk the children and look for an MTElse. 
    315312                # the children of the MTElse will become $tokens 
    316                 for my $tok (@{ $t->[2] }) { 
    317                     if (lc $tok->[0] eq 'else' || lc $tok->[0] eq 'elseif') { 
    318                         $tokens = $tok->[2]; 
    319                         $uncompiled = $tok->[3]; 
     313                for my $tok (@{ $t->childNodes }) { 
     314                    my $tag = lc $tok->tag; 
     315                    if ($tag eq 'else' || $tag eq 'elseif') { 
     316                        $tokens = $tok->childNodes; 
     317                        $uncompiled = $tok->nodeValue; 
    320318                        last; 
    321319                    } 
     
    323321                next unless $tokens; 
    324322            } else { 
    325                 if ($t->[2] && ref($t->[2])) { 
     323                my $childNodes = $t->childNodes; 
     324                if ($childNodes && ref($childNodes)) { 
    326325                    # either there is no cond for this tag, or it's true, 
    327326                    # so we want to partition the children into 
    328327                    # those which are inside an else and those which are not. 
    329328                    ($tokens, $tokens_else) = ([], []); 
    330                     for my $sub (@{ $t->[2] }) { 
    331                         if (lc $sub->[0] eq 'else' || lc $sub->[0] eq 'elseif') { 
     329                    for my $sub (@$childNodes) { 
     330                        my $tag = lc $sub->tag; 
     331                        if ($tag eq 'else' || $tag eq 'elseif') { 
    332332                            push @$tokens_else, $sub; 
    333333                        } else { 
     
    336336                    } 
    337337                } 
    338                 $uncompiled = $t->[3]
    339             } 
    340             my($h, $type) = $ctx->handler_for($t->[0]); 
     338                $uncompiled = $t->nodeValue
     339            } 
     340            my($h, $type) = $ctx->handler_for($t->tag); 
    341341            if ($h) { 
    342342                $timer->pause_partial if $timer; 
    343                 local($ctx->{__stash}{tag}) = $t->[0]
     343                local($ctx->{__stash}{tag}) = $t->tag
    344344                local($ctx->{__stash}{tokens}) = ref($tokens) ? bless $tokens, 'MT::Template::Tokens' : undef; 
    345345                local($ctx->{__stash}{tokens_else}) = ref($tokens_else) ? bless $tokens_else, 'MT::Template::Tokens' : undef; 
    346346                local($ctx->{__stash}{uncompiled}) = $uncompiled; 
    347                 my %args = %{$t->[1]} if defined $t->[1]
    348                 my @args = @{$t->[4]} if defined $t->[4]
     347                my %args = %{$t->attributes} if defined $t->attributes
     348                my @args = @{$t->attribute_list} if defined $t->attribute_list
    349349 
    350350                # process variables 
     
    387387                    my $err = $ctx->errstr; 
    388388                    if (defined $err) { 
    389                         return $build->error(MT->translate("Error in <mt[_1]> tag: [_2]", $t->[0], $ctx->errstr)); 
     389                        return $build->error(MT->translate("Error in <mt[_1]> tag: [_2]", $t->tag, $ctx->errstr)); 
    390390                    } 
    391391                    else { 
     
    414414                if ($timer) { 
    415415                    $timer->mark("tag_" 
    416                         . lc($t->[0]) . args_to_string(\%args)); 
     416                        . lc($t->tag) . args_to_string(\%args)); 
    417417                } 
    418418            } else { 
    419                 if ($t->[0] !~ m/^_/) { # placeholder tag. just ignore 
    420                     return $build->error(MT->translate("Unknown tag found: [_1]", $t->[0])); 
     419                if ($t->tag !~ m/^_/) { # placeholder tag. just ignore 
     420                    return $build->error(MT->translate("Unknown tag found: [_1]", $t->tag)); 
    421421                } 
    422422            } 
  • trunk/lib/MT/CMS/Template.pm

    r2887 r2973  
    145145            foreach my $tag (@$includes) { 
    146146                my $include = {}; 
    147                 my $mod = $include->{include_module} = $tag->[1]->{module} || $tag->[1]->{widget}; 
     147                my $attr = $tag->attributes; 
     148                my $mod = $include->{include_module} = $attr->{module} || $attr->{widget}; 
    148149                next unless $mod; 
    149                 my $type = $tag->[1]->{widget} ? 'widget' : 'custom'; 
     150                my $type = $attr->{widget} ? 'widget' : 'custom'; 
    150151                next if exists $seen{$type}{$mod}; 
    151152                $seen{$type}{$mod} = 1; 
     
    208209            my %seen; 
    209210            foreach my $set (@sets) { 
    210                 my $name = $set->[1]->{name}; 
     211                my $name = $set->attributes->{name}; 
    211212                next unless $name; 
    212213                next if $seen{$name}; 
  • trunk/lib/MT/Template.pm

    r2882 r2973  
    1111use MT::Util qw( weaken ); 
    1212 
     13use MT::Template::Node; 
    1314sub NODE () { 'MT::Template::Node' } 
    14  
    15 sub NODE_TEXT ()     { 1 } 
    16 sub NODE_BLOCK ()    { 2 } 
    17 sub NODE_FUNCTION () { 3 } 
    1815 
    1916my $resync_to_db; 
     
    188185    my $str = ''; 
    189186    foreach my $token (@$tokens) { 
    190         if ($token->[0] eq 'TEXT') { 
    191             $str .= $token->[1]; 
     187        my $tag = $token->tag; 
     188        if ($tag eq 'TEXT') { 
     189            $str .= $token->nodeValue; 
    192190        } else { 
    193             my $tag = $token->[0]; 
    194191            $str .= '<mt' . $tag; 
    195             if (my $attrs = $token->[4]) { 
    196                 my $attrh = $token->[1]
     192            if (my $attrs = $token->attribute_list) { 
     193                my $attrh = $token->attributes
    197194                foreach my $a (@$attrs) { 
    198195                    delete $attrh->{$a->[0]}; 
     
    208205            } 
    209206            $str .= '>'; 
    210             if ($token->[2]) { 
     207            if (my $childNodes = $token->childNodes) { 
    211208                # container tag 
    212                 $str .= $tmpl->reflow( $token->[2] ); 
     209                $str .= $tmpl->reflow($childNodes); 
    213210                $str .= '</mt' . $tag . '>'; 
    214211            } 
     
    552549    return unless $tokens; 
    553550    foreach my $t (@$tokens) { 
    554         if ($t->[0] ne 'TEXT') { 
    555             if ($t->[1]->{id}) { 
     551        if ($t->tag ne 'TEXT') { 
     552            if (my $id = $t->getAttribute('id')) { 
    556553                my $ids = $tmpl->{__ids} ||= {}; 
    557                 $ids->{lc $t->[1]->{id}} = $t; 
     554                $ids->{lc $id} = $t; 
    558555            } 
    559             elsif ($t->[1]->{class}) { 
     556            elsif (my $class = $t->getAttribute('class')) { 
    560557                my $classes = $tmpl->{__classes} ||= {}; 
    561                 push @{ $classes->{lc $t->[1]->{class}} ||= [] }, $t; 
     558                push @{ $classes->{lc $class} ||= [] }, $t; 
    562559            } 
    563             $tmpl->rescan($t->[2]) if $t->[2]; 
     560            if (my $childNodes = $t->childNodes) { 
     561                $tmpl->rescan($childNodes); 
     562            } 
    564563        } 
    565564    } 
     
    712711    my ($id) = @_; 
    713712    if (my $node = $tmpl->token_ids->{$id}) { 
    714         return bless $node, NODE
     713        return $node
    715714    } 
    716715    undef; 
     
    720719    my $tmpl = shift; 
    721720    my ($tag, $attr) = @_; 
    722     my $node = bless [ $tag, $attr, undef, undef, undef, undef, $tmpl ], NODE; 
    723     weaken($node->[6]); 
    724     return $node; 
     721    return NODE->new(tag => $tag, attributes => $attr, template => $tmpl); 
    725722} 
    726723 
     
    728725    my $tmpl = shift; 
    729726    my ($text) = @_; 
    730     my $node = bless [ 'TEXT', $text, undef, undef, undef, undef, $tmpl ], NODE; 
    731     weaken($node->[6]); 
    732     return $node; 
     727    return NODE->new(tag => 'TEXT', nodeValue => $text, template => $tmpl); 
    733728} 
    734729 
     
    809804 
    810805use strict; 
    811 sub NODE_TEXT ()     { 1 } 
    812 sub NODE_BLOCK ()    { 2 } 
    813 sub NODE_FUNCTION () { 3 } 
    814806 
    815807sub getElementsByTagName { 
     
    818810    $name = lc $name; 
    819811    foreach my $t (@$tokens) { 
    820         if (lc $t->[0] eq $name) { 
     812        if (lc $t->tag eq $name) { 
    821813            push @list, $t; 
    822814        } 
    823         if ($t->[2]) { 
    824             my $subt = getElementsByTagName($t->[2], $name); 
     815        if (my $childNodes = $t->childNodes) { 
     816            my $subt = getElementsByTagName($childNodes, $name); 
    825817            push @list, @$subt if $subt; 
    826818        } 
     
    834826    $name = lc $name; 
    835827    foreach my $t (@$tokens) { 
    836         if ((ref($t->[1]) eq 'HASH') && (lc ($t->[1]{'name'} || '') eq $name)) { 
     828        if (lc ($t->getAttribute('name') || '') eq $name) { 
    837829            push @list, $t; 
    838830        } 
    839         if ($t->[2]) { 
    840             my $subt = getElementsByName($t->[2], $name); 
     831        if (my $childNodes = $t->childNodes) { 
     832            my $subt = getElementsByName($childNodes, $name); 
    841833            push @list, @$subt if $subt; 
    842834        } 
     
    844836    scalar @list ? \@list : undef; 
    845837} 
    846  
    847 package MT::Template::Node; 
    848  
    849 use strict; 
    850 use MT::Util qw( weaken ); 
    851  
    852 sub setAttribute { 
    853     my $node = shift; 
    854     my ($attr, $val) = @_; 
    855     if ($attr eq 'id') { 
    856         # assign into ids 
    857         my $tmpl = $node->template; 
    858         my $ids = $tmpl->token_ids; 
    859         my $old_id = $node->getAttribute("id"); 
    860         if ($old_id && $ids) { 
    861             delete $ids->{$old_id}; 
    862         } 
    863     } 
    864     elsif ($attr eq 'class') { 
    865         # assign into classes 
    866         my $tmpl = $node->template; 
    867         my $classes = $tmpl->token_classes; 
    868         my $old_class = $node->getAttribute("class"); 
    869         if ($old_class && $classes->{$old_class}) { 
    870             @{$classes->{$old_class}} = grep { $_ != $node } 
    871                 @{$classes->{$old_class}}; 
    872         } 
    873         push @{$classes->{$val} ||= []}, $node; 
    874     } 
    875     ($node->[1] ||= {})->{$attr} = $val; 
    876 } 
    877  
    878 sub template { 
    879     my $node = shift; 
    880     return $node->[6]; 
    881 } 
    882  
    883 sub getAttribute { 
    884     my $node = shift; 
    885     my ($attr) = @_; 
    886     ($node->[1] || {})->{$attr}; 
    887 } 
    888  
    889 # sub attributes { 
    890 #     my $node = shift; 
    891 #     return $node->[1] ||= {}; 
    892 # } 
    893  
    894 sub nextSibling { 
    895     my $node = shift; 
    896     my $parent = $node->parentNode->childNodes; 
    897     my $max = (scalar @$parent) - 1; 
    898     return undef unless $max; 
    899     my $last = $parent->[0]; 
    900     foreach my $n ($parent->[1..$max]) { 
    901         return $n if $node == $last; 
    902         $last = $n; 
    903     } 
    904     return $parent->[$max] if $node == $last; 
    905     return undef; 
    906 } 
    907  
    908 sub lastChild { 
    909     my $node = shift; 
    910     my $children = $node->childNodes or return undef; 
    911     @$children ? $children->[scalar @$children - 1] : undef; 
    912 } 
    913  
    914 sub firstChild { 
    915     my $node = shift; 
    916     my $children = $node->[2] or return undef; 
    917     @$children ? $children->[0] : undef; 
    918 } 
    919  
    920 sub previousSibling { 
    921     my $node = shift; 
    922     my $parent = $node->parentNode->childNodes; 
    923     my $last; 
    924     foreach my $n (@$parent) { 
    925         return $last if $node == $n; 
    926         $last = $n; 
    927     } 
    928     return undef; 
    929 } 
    930  
    931 sub parentNode { 
    932     my $node = shift; 
    933     weaken($node->[5] = shift) if @_; 
    934     $node->[5]; 
    935 } 
    936  
    937 sub childNodes { 
    938     my $node = shift; 
    939     $node->[2] = shift if @_; 
    940     $node->[2]; 
    941 } 
    942  
    943 sub ownerDocument { #template 
    944     my $node = shift; 
    945     return $node->template; 
    946 } 
    947  
    948 sub hasChildNodes { 
    949     my $node = shift; 
    950     $node->[2] && (@{$node->[2]}) ? 1 : 0; 
    951 } 
    952  
    953 sub nodeType { 
    954     my $node = shift; 
    955     if ($node->[0] eq 'TEXT') { 
    956         return NODE_TEXT(); 
    957     } elsif (defined $node->[2]) { 
    958         return NODE_BLOCK(); 
    959     } else { 
    960         return NODE_FUNCTION(); 
    961     } 
    962 } 
    963  
    964 sub nodeName { 
    965     my $node = shift; 
    966     if ($node->[0] eq 'TEXT') { 
    967         return undef; 
    968     } 
    969     # normalize: 
    970     #    MTEntry => mt:entry 
    971     #    MTAPP:WIDGET => mtapp:widget 
    972     my $tag = lc $node->[0]; 
    973     if (($tag !~ m/:/) && ($tag =~ m/^mt/)) { 
    974         $tag =~ s/^mt/mt:/; 
    975     } 
    976     return $tag; 
    977 } 
    978  
    979 # Returns text of a text node; inner text for a block tag, or undef 
    980 # for a function tag. 
    981 sub nodeValue { 
    982     my $node = shift; 
    983     if ($node->[0] eq 'TEXT') { 
    984         return $node->[1]; 
    985     } else { 
    986         if (defined $node->[3]) { 
    987             return $node->[3]; 
    988         } 
    989     } 
    990     return undef; 
    991 } 
    992  
    993 sub innerHTML { 
    994     my $node = shift; 
    995     if (@_) { 
    996         my ($text) = @_; 
    997         $node->[3] = $text; 
    998         my $builder = new MT::Builder; 
    999         my $ctx = MT::Template::Context->new; 
    1000         $node->[2] = $builder->compile($ctx, $text); 
    1001         my $tmpl = $node->ownerDocument; 
    1002         if ($tmpl) { 
    1003             $tmpl->reset_markers; 
    1004             $tmpl->{reflow_flag} = 1; 
    1005         } 
    1006     } 
    1007     return $node->[3]; 
    1008 } 
    1009  
    1010 # TBD: what about new nodes that are added with id elements? 
    1011 sub appendChild { 
    1012     my $node = shift; 
    1013     my ($new_node) = @_; 
    1014     my $nodes = $node->childNodes; 
    1015     push @$nodes, $new_node; 
    1016     my $tmpl = $node->ownerDocument; 
    1017     if ($tmpl) { 
    1018         $tmpl->{reflow_flag} = 1; 
    1019     } 
    1020 } 
    1021  
    1022 sub removeChild { 
    1023     my $node = shift; 
    1024 } 
    1025  
    1026 *inner_html = \&innerHTML; 
    1027 *append_child = \&appendChild; 
    1028 *insert_before = \&insertBefore; 
    1029 *remove_child = \&removeChild; 
    1030838 
    1031839# trans('Index')