Changeset 14711


Ignore:
Timestamp:
05/07/12 09:44:34 (13 months ago)
Author:
MichaelDaum
Message:

Item11808:Item11825:

  • reverting perltidy
  • modernized plugin by using a proper OO-core
  • fixed processing of =tokenize= properly
  • added =replace= parameter for FORMATLIST
  • fixed the plugin calling =Foswiki::Func::expandCommonVariables()= itself unnecessarily
Location:
trunk/FilterPlugin
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/FilterPlugin/data/System/FilterPlugin.txt

    r13591 r14711  
    8585   * tokenize="...": regex to tokenize the list before spliting it up, tokens are inserted back again after the split stage has been passed 
    8686   * split="...": the split expression (default ",") 
     87   * replace="key1=value1,key2=value2, ...": this allows to preprocess each list item by replacing the given keys with their value 
    8788   * pattern="...": pattern applied to each item (default "\s(.*)\s") 
    8889   * format="...": the format string for each item (default "$1") 
     
    102103   * marker="...": string to be inserted when the =selection= regex matches; this will be inserted at the position =$marker= as 
    103104     indicated in =format= . 
    104    * map="key1=value1,key2=value2, ...": this establishes a key-value hash available via the =$map()= variable. 
     105   * map="key1=value1,key2=value2, ...": this establishes a key-value hash available via the =$map()= variable. (see also the =replace= parameter for means 
     106     to preprocess list items automatically.) 
    105107 
    106108The pattern string shall group matching substrings in the list item to which you can refer to by  
     
    265267|  Version: | %$VERSION% | 
    266268|  Change History: | <!-- versions below in reverse order -->&nbsp; | 
     269|  19 Apr 2012: | modernized plugin by using a proper OO-core; \ 
     270                  fixed processing of =tokenize= properly;\ 
     271                  added =replace= parameter for FORMATLIST; \ 
     272                  fixed the plugin calling =Foswiki::Func::expandCommonVariables()= itself unnecessarily  | 
    267273|  10 Jan 2012: | fixed filtering zero; fixed counting list items without formating them; added =hideempty= parameter to enable/disable rendering empty list items | 
    268274|  29 Sep 2011: | fixed SUBST macro =topic= param processing embedded META | 
  • trunk/FilterPlugin/lib/Foswiki/Plugins/FilterPlugin.pm

    r14686 r14711  
    1111# but WITHOUT ANY WARRANTY; without even the implied warranty of 
    1212# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    13 # GNU General Public License for more details, published at 
     13# GNU General Public License for more details, published at  
    1414# http://www.gnu.org/copyleft/gpl.html 
    1515# 
    1616############################################################################### 
    1717package Foswiki::Plugins::FilterPlugin; 
     18 
    1819use strict; 
     20use warnings; 
    1921 
    20 ############################################################################### 
    21 use vars qw( 
    22   $currentWeb $currentTopic $VERSION $RELEASE 
    23   $NO_PREFS_IN_TOPIC $SHORTDESCRIPTION 
    24   $doneInitCore 
    25 ); 
     22use Foswiki::Func(); 
    2623 
    27 $VERSION          = '$Rev$'; 
    28 $RELEASE           = '2.08'; 
    29 $NO_PREFS_IN_TOPIC = 1; 
    30 $SHORTDESCRIPTION = 
    31 'Substitute and extract information from content by using regular expressions'; 
     24our $VERSION = '$Rev$'; 
     25our $RELEASE = '3.00'; 
     26our $NO_PREFS_IN_TOPIC = 1; 
     27our $SHORTDESCRIPTION = 'Substitute and extract information from content by using regular expressions'; 
     28our $core; 
    3229 
    3330############################################################################### 
    3431sub initPlugin { 
    35     ( $currentTopic, $currentWeb ) = @_; 
     32  my ($currentTopic, $currentWeb) = @_; 
    3633 
    37     Foswiki::Func::registerTagHandler( 'FORMATLIST', \&handleFormatList ); 
    38     Foswiki::Func::registerTagHandler( 'MAKEINDEX',  \&handleMakeIndex ); 
    39     Foswiki::Func::registerTagHandler( 'SUBST',      \&handleSubst ); 
    40     Foswiki::Func::registerTagHandler( 'EXTRACT',    \&handleExtract ); 
     34  Foswiki::Func::registerTagHandler('FORMATLIST', sub { 
     35    return getCore(shift)->handleFormatList(@_); 
     36  }); 
    4137 
    42     $doneInitCore = 0; 
    43     return 1; 
     38  Foswiki::Func::registerTagHandler('MAKEINDEX', sub { 
     39    return getCore(shift)->handleMakeIndex(@_); 
     40  }); 
     41 
     42  Foswiki::Func::registerTagHandler('SUBST', sub { 
     43    return getCore(shift)->handleSubst(@_); 
     44  }); 
     45 
     46  Foswiki::Func::registerTagHandler('EXTRACT', sub { 
     47    return getCore(shift)->handleExtract(@_); 
     48  }); 
     49 
     50  $core = undef; 
     51  return 1; 
    4452} 
    4553 
    4654############################################################################### 
    4755sub commonTagsHandler { 
    48     while ( $_[0] =~ 
    49 s/%STARTSUBST{(?!.*%STARTSUBST)(.*?)}%(.*?)%STOPSUBST%/&handleFilterArea($1, 1, $2)/ges 
    50       ) 
    51     { 
     56# my ($text, $topic, $web, $included, $meta ) = @_; 
    5257 
    53         # nop 
    54     } 
    55     while ( $_[0] =~ 
    56 s/%STARTEXTRACT{(?!.*%STARTEXTRACT)(.*?)}%(.*?)%STOPEXTRACT%/&handleFilterArea($1, 0, $2)/ges 
    57       ) 
    58     { 
     58  my $theTopic = $_[1]; 
     59  my $theWeb = $_[2]; 
    5960 
    60         # nop 
    61     } 
     61  while($_[0] =~ s/%STARTSUBST{(?!.*%STARTSUBST)(.*?)}%(.*?)%STOPSUBST%/&handleFilterArea($1, 1, $2, $theWeb, $theTopic)/ges) { 
     62    # nop 
     63  } 
     64  while($_[0] =~ s/%STARTEXTRACT{(?!.*%STARTEXTRACT)(.*?)}%(.*?)%STOPEXTRACT%/&handleFilterArea($1, 0, $2, $theWeb, $theTopic)/ges) { 
     65    # nop 
     66  } 
    6267} 
    6368 
    6469############################################################################### 
    65 sub initCore { 
     70sub getCore { 
     71  my $session = shift; 
    6672 
    67     return if $doneInitCore; 
    68     $doneInitCore = 1; 
     73  unless (defined $core) { 
     74    require Foswiki::Plugins::FilterPlugin::Core; 
     75    $core = new Foswiki::Plugins::FilterPlugin::Core($session) 
     76  } 
    6977 
    70     require Foswiki::Plugins::FilterPlugin::Core; 
    71     Foswiki::Plugins::FilterPlugin::Core::init( $currentWeb, $currentTopic ); 
     78  return $core; 
    7279} 
    7380 
    7481############################################################################### 
    7582sub handleFilterArea { 
    76     initCore(); 
    77     return Foswiki::Plugins::FilterPlugin::Core::handleFilterArea(@_); 
    78 } 
    79  
    80 ############################################################################### 
    81 sub handleFormatList { 
    82     initCore(); 
    83     return Foswiki::Plugins::FilterPlugin::Core::handleFormatList(@_); 
    84 } 
    85  
    86 ############################################################################### 
    87 sub handleMakeIndex { 
    88     initCore(); 
    89     return Foswiki::Plugins::FilterPlugin::Core::handleMakeIndex(@_); 
    90 } 
    91  
    92 ############################################################################### 
    93 sub handleSubst { 
    94     initCore(); 
    95     return Foswiki::Plugins::FilterPlugin::Core::handleSubst(@_); 
    96 } 
    97  
    98 ############################################################################### 
    99 sub handleExtract { 
    100     initCore(); 
    101     return Foswiki::Plugins::FilterPlugin::Core::handleExtract(@_); 
     83  return getCore()->handleFilterArea(@_); 
    10284} 
    10385 
  • trunk/FilterPlugin/lib/Foswiki/Plugins/FilterPlugin/Core.pm

    r14686 r14711  
    1111# but WITHOUT ANY WARRANTY; without even the implied warranty of 
    1212# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    13 # GNU General Public License for more details, published at 
     13# GNU General Public License for more details, published at  
    1414# http://www.gnu.org/copyleft/gpl.html 
    1515# 
     
    1717 
    1818package Foswiki::Plugins::FilterPlugin::Core; 
     19 
    1920use strict; 
    20  
    21 use vars 
    22   qw($currentTopic $currentWeb %seenAnchorNames $makeIndexCounter %filteredTopic); 
     21use warnings; 
     22 
    2323use POSIX qw(ceil); 
     24use Foswiki::Plugins(); 
    2425use Foswiki::Func(); 
    2526 
    26 use constant DEBUG => 0;    # toggle me 
    27  
    28 ############################################################################### 
    29 sub init { 
    30     ( $currentWeb, $currentTopic ) = @_; 
    31  
    32     %seenAnchorNames  = (); 
    33     %filteredTopic    = (); 
    34     $makeIndexCounter = 0; 
    35 } 
    36  
    37 ############################################################################### 
    38 sub writeDebug { 
    39     print STDERR "- FilterPlugin - $_[0]\n" if DEBUG; 
     27use constant DEBUG => 0; # toggle me 
     28 
     29############################################################################### 
     30sub new { 
     31  my ($class, $session) = @_; 
     32 
     33  $session ||= $Foswiki::Plugins::SESSION; 
     34 
     35  my $this = bless({ 
     36    session => $session, 
     37    seenAnchorNames => {}, 
     38    makeIndexCounter => 0, 
     39    filteredTopic => {}, 
     40  }, $class); 
     41 
     42  return $this; 
    4043} 
    4144 
    4245############################################################################### 
    4346sub handleFilterArea { 
    44     my ( $theAttributes, $theMode, $theText ) = @_; 
    45  
    46     $theAttributes ||= ''; 
    47  
    48     #writeDebug("called handleFilterArea($theAttributes)"); 
    49  
    50     my %params = Foswiki::Func::extractParameters($theAttributes); 
    51     return handleFilter( \%params, $theMode, $theText ); 
     47  my ($this, $theAttributes, $theMode, $theText, $theWeb, $theTopic) = @_; 
     48 
     49  $theAttributes ||= ''; 
     50  #writeDebug("called handleFilterArea($theAttributes)"); 
     51 
     52  my %params = Foswiki::Func::extractParameters($theAttributes); 
     53  return $this->handleFilter(\%params, $theMode, $theText, $theWeb, $theTopic); 
    5254} 
    5355 
     
    6264# 
    6365sub handleFilter { 
    64     my ( $params, $theMode, $theText ) = @_; 
    65  
    66     #writeDebug("called handleFilter(".$params->stringify.")"); 
    67     #writeDebug("theMode = '$theMode'"); 
    68  
    69     # get parameters 
    70     my $thePattern    = $params->{pattern} || ''; 
    71     my $theFormat     = $params->{format}  || ''; 
    72     my $theNullFormat = $params->{null}    || ''; 
    73     my $theHeader     = $params->{header}  || ''; 
    74     my $theFooter     = $params->{footer}  || ''; 
    75     my $theLimit      = $params->{limit}   || $params->{hits} || 100000; 
    76     my $theSkip       = $params->{skip}    || 0; 
    77     my $theExpand     = $params->{expand}  || 'on'; 
    78     my $theSeparator = $params->{separator}; 
    79     my $theExclude   = $params->{exclude} || ''; 
    80     my $theInclude   = $params->{include} || ''; 
    81     my $theSort      = $params->{sort} || 'off'; 
    82     my $theReverse   = $params->{reverse} || ''; 
    83  
    84     my $theTopic = $params->{_DEFAULT} || $params->{topic} || $currentTopic; 
    85     my $theWeb = $currentWeb; 
    86  
    87     ( $theWeb, $theTopic ) = 
    88       Foswiki::Func::normalizeWebTopicName( $theWeb, $theTopic ); 
    89     $theWeb =~ s/\//\./g; 
    90  
    91     $theText ||= $params->{text}; 
    92  
    93     $theSeparator = '' unless defined $theSeparator; 
    94  
    95     # get the source text 
    96     my $text = ''; 
    97     if ( defined $theText ) {    # direct text 
    98         $text = $theText; 
    99     } 
    100     else {                       # topic text 
    101         return '' if $filteredTopic{"$theWeb.$theTopic"}; 
    102         $filteredTopic{"$theWeb.$theTopic"} = 1; 
    103         ( undef, $text ) = Foswiki::Func::readTopic( $theWeb, $theTopic ); 
    104         if ( $text =~ /^No permission to read topic/ ) { 
    105             return showError("$text"); 
     66  my ($this, $params, $theMode, $theText, $theWeb, $theTopic) = @_; 
     67 
     68  #writeDebug("called handleFilter(".$params->stringify.")"); 
     69  #writeDebug("theMode = '$theMode'"); 
     70 
     71  # get parameters 
     72  my $thePattern = $params->{pattern} || ''; 
     73  my $theFormat = $params->{format} || ''; 
     74  my $theNullFormat = $params->{null} || ''; 
     75  my $theHeader = $params->{header} || ''; 
     76  my $theFooter = $params->{footer} || ''; 
     77  my $theLimit = $params->{limit} || $params->{hits} || 100000;  
     78  my $theSkip = $params->{skip} || 0; 
     79  my $theExpand = $params->{expand} || 'on'; 
     80  my $theSeparator = $params->{separator}; 
     81  my $theExclude = $params->{exclude} || ''; 
     82  my $theInclude = $params->{include} || ''; 
     83  my $theSort = $params->{sort} || 'off'; 
     84  my $theReverse = $params->{reverse} || ''; 
     85 
     86  my $thisTopic = $params->{_DEFAULT} || $params->{topic} || $theTopic; 
     87  ($theWeb, $theTopic) = Foswiki::Func::normalizeWebTopicName($theWeb, $thisTopic); 
     88  $theWeb =~ s/\//\./g; 
     89   
     90  $theText ||= $params->{text}; 
     91 
     92  $theSeparator = '' unless defined $theSeparator; 
     93 
     94  # get the source text 
     95  my $text = ''; 
     96  if (defined $theText) { # direct text 
     97    $text = $theText; 
     98  } else { # topic text 
     99    return '' if $this->{filteredTopic}{"$theWeb.$theTopic"}; 
     100    $this->{filteredTopic}{"$theWeb.$theTopic"} = 1; 
     101    (undef, $text) = Foswiki::Func::readTopic($theWeb, $theTopic); 
     102    $text = '' unless defined $text; 
     103    if ($text =~ /^No permission to read topic/) { 
     104      return inlineError("$text"); 
     105    } 
     106    if ($text =~ /%STARTINCLUDE%(.*)%STOPINCLUDE%/gs) { 
     107      $text = $1; 
     108      if ($theExpand eq 'on') { 
     109        $text = Foswiki::Func::expandCommonVariables($text); 
     110        $text = Foswiki::Func::renderText($text); 
     111      } 
     112    } 
     113  } 
     114  #writeDebug("text = '$text'"); 
     115 
     116  my $result = ''; 
     117  my $hits = $theLimit; 
     118  my $skip = $theSkip; 
     119  if ($theMode == 0) { 
     120    # extraction mode 
     121 
     122    my @result = (); 
     123    while($text =~ /$thePattern/gms) { 
     124      my $arg1 = $1; 
     125      my $arg2 = $2; 
     126      my $arg3 = $3; 
     127      my $arg4 = $4; 
     128      my $arg5 = $5; 
     129      my $arg6 = $6; 
     130      my $arg7 = $7; 
     131      my $arg8 = $8; 
     132      my $arg9 = $9; 
     133      my $arg10 = $10; 
     134 
     135      $arg1 = '' unless defined $arg1; 
     136      $arg2 = '' unless defined $arg2; 
     137      $arg3 = '' unless defined $arg3; 
     138      $arg4 = '' unless defined $arg4; 
     139      $arg5 = '' unless defined $arg5; 
     140      $arg6 = '' unless defined $arg6; 
     141      $arg7 = '' unless defined $arg7; 
     142      $arg8 = '' unless defined $arg8; 
     143      $arg9 = '' unless defined $arg9; 
     144      $arg10 = '' unless defined $arg10; 
     145 
     146      my $match = $theFormat; 
     147      $match =~ s/\$10/$arg10/g; 
     148      $match =~ s/\$1/$arg1/g; 
     149      $match =~ s/\$2/$arg2/g; 
     150      $match =~ s/\$3/$arg3/g; 
     151      $match =~ s/\$4/$arg4/g; 
     152      $match =~ s/\$5/$arg5/g; 
     153      $match =~ s/\$6/$arg6/g; 
     154      $match =~ s/\$7/$arg7/g; 
     155      $match =~ s/\$8/$arg8/g; 
     156      $match =~ s/\$9/$arg9/g; 
     157      next if $theExclude && $match =~ /^($theExclude)$/; 
     158      next if $theInclude && $match !~ /^($theInclude)$/; 
     159      next if $skip-- > 0; 
     160      push @result,$match; 
     161      $hits--; 
     162      last if $theLimit > 0 && $hits <= 0; 
     163    } 
     164    if ($theSort ne 'off') { 
     165      if ($theSort eq 'alpha' || $theSort eq 'on') { 
     166        @result = sort {uc($a) cmp uc($b)} @result; 
     167      } elsif ($theSort eq 'num') { 
     168        @result = sort {$a <=> $b} @result; 
     169      } 
     170    } 
     171    @result = reverse @result if $theReverse eq 'on'; 
     172    $result = join($theSeparator, @result); 
     173  } elsif ($theMode == 1) { 
     174    # substitution mode 
     175    $result = ''; 
     176    while($text =~ /(.*?)$thePattern/gcs) { 
     177      my $prefix = $1; 
     178      my $arg1 = $2; 
     179      my $arg2 = $3; 
     180      my $arg3 = $4; 
     181      my $arg4 = $5; 
     182      my $arg5 = $6; 
     183      my $arg6 = $7; 
     184      my $arg7 = $8; 
     185      my $arg8 = $9; 
     186      my $arg9 = $10; 
     187      my $arg10 = $11; 
     188 
     189      $arg1 = '' unless defined $arg1; 
     190      $arg2 = '' unless defined $arg2; 
     191      $arg3 = '' unless defined $arg3; 
     192      $arg4 = '' unless defined $arg4; 
     193      $arg5 = '' unless defined $arg5; 
     194      $arg6 = '' unless defined $arg6; 
     195      $arg7 = '' unless defined $arg7; 
     196      $arg8 = '' unless defined $arg8; 
     197      $arg9 = '' unless defined $arg9; 
     198      $arg10 = '' unless defined $arg10; 
     199 
     200      my $match = $theFormat; 
     201      $match =~ s/\$10/$arg10/g; 
     202      $match =~ s/\$1/$arg1/g; 
     203      $match =~ s/\$2/$arg2/g; 
     204      $match =~ s/\$3/$arg3/g; 
     205      $match =~ s/\$4/$arg4/g; 
     206      $match =~ s/\$5/$arg5/g; 
     207      $match =~ s/\$6/$arg6/g; 
     208      $match =~ s/\$7/$arg7/g; 
     209      $match =~ s/\$8/$arg8/g; 
     210      $match =~ s/\$9/$arg9/g; 
     211      next if $theExclude && $match =~ /^($theExclude)$/; 
     212      next if $theInclude && $match !~ /^($theInclude)$/; 
     213      next if $skip-- > 0; 
     214      #writeDebug("match=$match"); 
     215      $result .= $prefix.$match; 
     216      #writeDebug("($hits) result=$result"); 
     217      $hits--; 
     218      last if $theLimit > 0 && $hits <= 0; 
     219    } 
     220    if ($text =~ /\G(.*)$/s) { 
     221      $result .= $1; 
     222    } 
     223  } 
     224  $result = $theNullFormat unless $result; 
     225  $result = $theHeader.$result.$theFooter; 
     226  $result = expandVariables($result); 
     227 
     228  delete $this->{filteredTopic}{"$theWeb.$theTopic"}; 
     229 
     230  #writeDebug("result='$result'"); 
     231  return $result; 
     232} 
     233 
     234############################################################################### 
     235sub handleSubst { 
     236  my ($this, $params, $theTopic, $theWeb) = @_; 
     237  return $this->handleFilter($params, 1, undef, $theWeb, $theTopic); 
     238} 
     239 
     240############################################################################### 
     241sub handleExtract { 
     242  my ($this, $params, $theTopic, $theWeb) = @_; 
     243  return $this->handleFilter($params, 0, undef, $theWeb, $theTopic); 
     244} 
     245 
     246############################################################################### 
     247sub handleMakeIndex { 
     248  my ($this, $params, $theTopic, $theWeb) = @_; 
     249 
     250  #writeDebug("### called handleMakeIndex(".$params->stringify.")"); 
     251  my $theList = $params->{_DEFAULT} || $params->{list} || ''; 
     252  my $theCols = $params->{cols} || 3; 
     253  my $theFormat = $params->{format}; 
     254  my $theSort = $params->{sort} || 'on'; 
     255  my $theSplit = $params->{split}; 
     256  $theSplit = '\s*,\s*' unless defined $theSplit; 
     257 
     258  my $theUnique = $params->{unique} || ''; 
     259  my $theExclude = $params->{exclude} || ''; 
     260  my $theInclude = $params->{include} || ''; 
     261  my $theReverse = $params->{reverse} || ''; 
     262  my $thePattern = $params->{pattern} || ''; 
     263  my $theHeader = $params->{header} || ''; 
     264  my $theFooter = $params->{footer} || ''; 
     265  my $theGroup = $params->{group}; 
     266  my $theAnchorThreshold = $params->{anchorthreshold} || 0; 
     267 
     268 
     269  # sanitize params 
     270  $theAnchorThreshold =~ s/[^\d]//go; 
     271  $theAnchorThreshold = 0 unless $theAnchorThreshold; 
     272  $theUnique = ($theUnique eq 'on')?1:0; 
     273  $theGroup = " \$anchor<h3>\$group</h3>\n" unless defined $theGroup; 
     274 
     275  $theFormat = '$item' unless defined $theFormat; 
     276 
     277  my $maxCols = $theCols; 
     278  $maxCols =~ s/[^\d]//go; 
     279  $maxCols = 3 if $maxCols eq ''; 
     280  $maxCols = 1 if $maxCols < 1; 
     281 
     282  # compute the list 
     283  $theList = expandVariables($theList); 
     284 
     285  #writeDebug("theList=$theList"); 
     286 
     287  # create the item descriptors for each list item 
     288  my @theList = (); 
     289  my %seen = (); 
     290  foreach my $item (split(/$theSplit/, $theList)) { 
     291    next if $theExclude && $item =~ /^($theExclude)$/; 
     292    next if $theInclude && $item !~ /^($theInclude)$/; 
     293 
     294    $item =~ s/<nop>//go; 
     295    $item =~ s/^\s+//go; 
     296    $item =~ s/\s+$//go; 
     297    next unless $item; 
     298 
     299    #writeDebug("item='$item'"); 
     300 
     301    if ($theUnique) { 
     302      next if $seen{$item}; 
     303      $seen{$item} = 1; 
     304    } 
     305 
     306    my $crit = $item; 
     307    if ($crit =~ /\((.*?)\)/) { 
     308      $crit = $1; 
     309    } 
     310    if ($theSort eq 'nocase') { 
     311      $crit = uc($crit); 
     312    } 
     313    $crit =~ s/[^$Foswiki::regex{'mixedAlphaNum'}]//go; 
     314 
     315    my $group = $crit; 
     316    $group = substr($crit, 0, 1) unless $theSort eq 'num'; 
     317 
     318    my $itemFormat = $theFormat; 
     319    if ($thePattern && $item =~ m/$thePattern/) { 
     320      my $arg1 = $1; 
     321      my $arg2 = $2; 
     322      my $arg3 = $3; 
     323      my $arg4 = $4; 
     324      my $arg5 = $5; 
     325      my $arg6 = $6; 
     326      my $arg7 = $7; 
     327      my $arg8 = $8; 
     328      my $arg9 = $9; 
     329      my $arg10 = $10; 
     330 
     331      $arg1 = '' unless defined $arg1; 
     332      $arg2 = '' unless defined $arg2; 
     333      $arg3 = '' unless defined $arg3; 
     334      $arg4 = '' unless defined $arg4; 
     335      $arg5 = '' unless defined $arg5; 
     336      $arg6 = '' unless defined $arg6; 
     337      $arg7 = '' unless defined $arg7; 
     338      $arg8 = '' unless defined $arg8; 
     339      $arg9 = '' unless defined $arg9; 
     340      $arg10 = '' unless defined $arg10; 
     341 
     342      $item = $arg1 if $arg1; 
     343      $itemFormat =~ s/\$10/$arg10/g; 
     344      $itemFormat =~ s/\$1/$arg1/g; 
     345      $itemFormat =~ s/\$2/$arg2/g; 
     346      $itemFormat =~ s/\$3/$arg3/g; 
     347      $itemFormat =~ s/\$4/$arg4/g; 
     348      $itemFormat =~ s/\$5/$arg5/g; 
     349      $itemFormat =~ s/\$6/$arg6/g; 
     350      $itemFormat =~ s/\$7/$arg7/g; 
     351      $itemFormat =~ s/\$8/$arg8/g; 
     352      $itemFormat =~ s/\$9/$arg9/g; 
     353    } 
     354 
     355    my %descriptor = ( 
     356      crit=>$crit, 
     357      item=>$item, 
     358      group=>$group, 
     359      format=>$itemFormat, 
     360    ); 
     361    #writeDebug("group=$descriptor{group}, item=$descriptor{item} crit=$descriptor{crit}"); 
     362    push @theList, \%descriptor; 
     363  } 
     364 
     365  my $listSize = scalar(@theList); 
     366  return '' unless $listSize; 
     367 
     368  # sort it 
     369  @theList = sort {$a->{crit} cmp $b->{crit}} @theList if $theSort =~ /nocase|on/; 
     370  @theList = sort {$a->{crit} <=> $b->{crit}} @theList if $theSort eq 'num'; 
     371  @theList = reverse @theList if $theReverse eq 'on'; 
     372 
     373  my $result = "<table class='fltLayoutTable' cellspacing='0' cellpadding='0'>\n<tr>\n"; 
     374 
     375  # - a col should at least contain a single group letter and one additional row  
     376  my $colSize = ceil($listSize / $maxCols); 
     377  #writeDebug("maxCols=$maxCols, colSize=$colSize, listSize=$listSize"); 
     378 
     379  my $listIndex = 0; 
     380  my $insideList = 0; 
     381  my $itemIndex = 0; 
     382  my $group = ''; 
     383  my @anchors = (); 
     384 
     385  foreach my $colIndex (1..$maxCols) { 
     386    $result .= "  <td valign='top'>\n"; 
     387 
     388    #writeDebug("new col"); 
     389    my $rowIndex = 1; 
     390    while (1) { 
     391      my $descriptor = $theList[$listIndex]; 
     392      my $format = $$descriptor{format}; 
     393      my $item = $$descriptor{item}; 
     394      #writeDebug("listIndex=$listIndex, itemIndex=$itemIndex, colIndex=$colIndex, rowIndex=$rowIndex, item=$item, format=$format"); 
     395 
     396      # construct group format 
     397      my $thisGroup = $$descriptor{group}; 
     398      my $cont = ''; 
     399      if (($theGroup && $group ne $thisGroup) || $rowIndex == 1) { 
     400        #last if $itemIndex % $colSize < 2 && $colIndex < $maxCols; # prevent schusterjunge 
     401 
     402        if ($thisGroup eq $group && $rowIndex == 1) { 
     403          $cont = " <span class='fltCont'>(cont.)</span>"; 
     404        } else { 
     405          $group = $thisGroup; 
    106406        } 
    107         if ( $text =~ /%STARTINCLUDE%(.*)%STOPINCLUDE%/gs ) { 
    108             $text = $1; 
    109             if ( $theExpand eq 'on' ) { 
    110                 $text = 
    111                   Foswiki::Func::expandCommonVariables( $text, $currentTopic, 
    112                     $currentWeb ); 
    113                 $text = Foswiki::Func::renderText( $text, $currentWeb ); 
    114             } 
     407 
     408        if ($insideList) { 
     409          $result .= "</ul>\n"; 
     410          $insideList = 0; 
    115411        } 
    116     } 
    117  
    118     #writeDebug("text = '$text'"); 
    119  
    120     my $result = ''; 
    121     my $hits   = $theLimit; 
    122     my $skip   = $theSkip; 
    123     if ( $theMode == 0 ) { 
    124  
    125         # extraction mode 
    126         my @result = (); 
    127         while ( $text =~ /$thePattern/gms ) { 
    128             my $arg1  = $1; 
    129             my $arg2  = $2; 
    130             my $arg3  = $3; 
    131             my $arg4  = $4; 
    132             my $arg5  = $5; 
    133             my $arg6  = $6; 
    134             my $arg7  = $7; 
    135             my $arg8  = $8; 
    136             my $arg9  = $9; 
    137             my $arg10 = $10; 
    138  
    139             $arg1  = '' unless defined $arg1; 
    140             $arg2  = '' unless defined $arg2; 
    141             $arg3  = '' unless defined $arg3; 
    142             $arg4  = '' unless defined $arg4; 
    143             $arg5  = '' unless defined $arg5; 
    144             $arg6  = '' unless defined $arg6; 
    145             $arg7  = '' unless defined $arg7; 
    146             $arg8  = '' unless defined $arg8; 
    147             $arg9  = '' unless defined $arg9; 
    148             $arg10 = '' unless defined $arg10; 
    149  
    150             my $match = $theFormat; 
    151             $match =~ s/\$10/$arg10/g; 
    152             $match =~ s/\$1/$arg1/g; 
    153             $match =~ s/\$2/$arg2/g; 
    154             $match =~ s/\$3/$arg3/g; 
    155             $match =~ s/\$4/$arg4/g; 
    156             $match =~ s/\$5/$arg5/g; 
    157             $match =~ s/\$6/$arg6/g; 
    158             $match =~ s/\$7/$arg7/g; 
    159             $match =~ s/\$8/$arg8/g; 
    160             $match =~ s/\$9/$arg9/g; 
    161             next if $theExclude && $match =~ /^($theExclude)$/; 
    162             next if $theInclude && $match !~ /^($theInclude)$/; 
    163             next if $skip-- > 0; 
    164             push @result, $match; 
    165             $hits--; 
    166             last if $theLimit > 0 && $hits <= 0; 
     412 
     413        # create an anchor to this group 
     414        my $anchor = ''; 
     415        if ($theGroup =~ /\$anchor/) { 
     416          $anchor = $this->getAnchorName($group); 
     417          if ($anchor)  { 
     418            push @anchors, { 
     419              name=>$anchor, 
     420              title=>$group, 
     421            }; 
     422            $anchor = "<a class='fltAnchor' name='$anchor'></a>"; 
     423          } 
    167424        } 
    168         if ( $theSort ne 'off' ) { 
    169             if ( $theSort eq 'alpha' || $theSort eq 'on' ) { 
    170                 @result = sort { uc($a) cmp uc($b) } @result; 
    171             } 
    172             elsif ( $theSort eq 'num' ) { 
    173                 @result = sort { $a <=> $b } @result; 
    174             } 
    175         } 
    176         @result = reverse @result if $theReverse eq 'on'; 
    177         $result = join( $theSeparator, @result ); 
    178     } 
    179     elsif ( $theMode == 1 ) { 
    180  
    181         # substitution mode 
    182         $result = ''; 
    183         while ( $text =~ /(.*?)$thePattern/gcs ) { 
    184             my $prefix = $1; 
    185             my $arg1   = $2; 
    186             my $arg2   = $3; 
    187             my $arg3   = $4; 
    188             my $arg4   = $5; 
    189             my $arg5   = $6; 
    190             my $arg6   = $7; 
    191             my $arg7   = $8; 
    192             my $arg8   = $9; 
    193             my $arg9   = $10; 
    194             my $arg10  = $11; 
    195  
    196             $arg1  = '' unless defined $arg1; 
    197             $arg2  = '' unless defined $arg2; 
    198             $arg3  = '' unless defined $arg3; 
    199             $arg4  = '' unless defined $arg4; 
    200             $arg5  = '' unless defined $arg5; 
    201             $arg6  = '' unless defined $arg6; 
    202             $arg7  = '' unless defined $arg7; 
    203             $arg8  = '' unless defined $arg8; 
    204             $arg9  = '' unless defined $arg9; 
    205             $arg10 = '' unless defined $arg10; 
    206  
    207             my $match = $theFormat; 
    208             $match =~ s/\$10/$arg10/g; 
    209             $match =~ s/\$1/$arg1/g; 
    210             $match =~ s/\$2/$arg2/g; 
    211             $match =~ s/\$3/$arg3/g; 
    212             $match =~ s/\$4/$arg4/g; 
    213             $match =~ s/\$5/$arg5/g; 
    214             $match =~ s/\$6/$arg6/g; 
    215             $match =~ s/\$7/$arg7/g; 
    216             $match =~ s/\$8/$arg8/g; 
    217             $match =~ s/\$9/$arg9/g; 
    218             next if $theExclude && $match =~ /^($theExclude)$/; 
    219             next if $theInclude && $match !~ /^($theInclude)$/; 
    220             next if $skip-- > 0; 
    221  
    222             #writeDebug("match=$match"); 
    223             $result .= $prefix . $match; 
    224  
    225             #writeDebug("($hits) result=$result"); 
    226             $hits--; 
    227             last if $theLimit > 0 && $hits <= 0; 
    228         } 
    229         if ( $text =~ /\G(.*)$/s ) { 
    230             $result .= $1; 
    231         } 
    232     } 
    233     $result = $theNullFormat unless $result; 
    234     $result = $theHeader . $result . $theFooter; 
    235     $result = 
    236       Foswiki::Func::expandCommonVariables( $result, $theTopic, $theWeb ) 
    237       if expandVariables($result); 
    238  
    239     delete $filteredTopic{"$theWeb.$theTopic"}; 
    240  
    241     #writeDebug("result='$result'"); 
    242     return $result; 
    243 } 
    244  
    245 ############################################################################### 
    246 sub handleSubst { 
    247     my ( $session, $params, $theTopic, $theWeb ) = @_; 
    248     return handleFilter( $params, 1 ); 
    249 } 
    250  
    251 ############################################################################### 
    252 sub handleExtract { 
    253     my ( $session, $params, $theTopic, $theWeb ) = @_; 
    254     return handleFilter( $params, 0 ); 
    255 } 
    256  
    257 ############################################################################### 
    258 sub handleMakeIndex { 
    259     my ( $session, $params, $theTopic, $theWeb ) = @_; 
    260  
    261     #writeDebug("### called handleMakeIndex(".$params->stringify.")"); 
    262     my $theList = $params->{_DEFAULT} || $params->{list} || ''; 
    263     my $theCols = $params->{cols} || 3; 
    264     my $theFormat = $params->{format}; 
    265     my $theSort   = $params->{sort} || 'on'; 
    266     my $theSplit  = $params->{split}; 
    267     $theSplit = ',' unless defined $theSplit; 
    268  
    269     my $theUnique          = $params->{unique}          || ''; 
    270     my $theExclude         = $params->{exclude}         || ''; 
    271     my $theInclude         = $params->{include}         || ''; 
    272     my $theReverse         = $params->{reverse}         || ''; 
    273     my $thePattern         = $params->{pattern}         || ''; 
    274     my $theHeader          = $params->{header}          || ''; 
    275     my $theFooter          = $params->{footer}          || ''; 
    276     my $theGroup           = $params->{group}; 
    277     my $theAnchorThreshold = $params->{anchorthreshold} || 0; 
    278  
    279     # sanitize params 
    280     $theAnchorThreshold =~ s/[^\d]//go; 
    281     $theAnchorThreshold = 0 unless $theAnchorThreshold; 
    282     $theUnique = ( $theUnique eq 'on' ) ? 1 : 0; 
    283     $theGroup = " \$anchor<h3>\$group</h3>\n" unless defined $theGroup; 
    284  
    285     $theFormat = '$item' unless defined $theFormat; 
    286  
    287     my $maxCols = $theCols; 
    288     $maxCols =~ s/[^\d]//go; 
    289     $maxCols = 3 if $maxCols eq ''; 
    290     $maxCols = 1 if $maxCols < 1; 
    291  
    292     # compute the list 
    293     $theList = 
    294       Foswiki::Func::expandCommonVariables( $theList, $theTopic, $theWeb ) 
    295       if expandVariables($theList); 
    296  
    297     #writeDebug("theList=$theList"); 
    298  
    299     # create the item descriptors for each list item 
    300     my @theList = (); 
    301     my %seen    = (); 
    302     foreach my $item ( split( /$theSplit/, $theList ) ) { 
    303         next if $theExclude && $item =~ /^($theExclude)$/; 
    304         next if $theInclude && $item !~ /^($theInclude)$/; 
    305  
    306         $item =~ s/<nop>//go; 
    307         $item =~ s/^\s+//go; 
    308         $item =~ s/\s+$//go; 
    309         next unless $item; 
    310  
    311         #writeDebug("item='$item'"); 
    312  
    313         if ($theUnique) { 
    314             next if $seen{$item}; 
    315             $seen{$item} = 1; 
    316         } 
    317  
    318         my $crit = $item; 
    319         if ( $crit =~ /\((.*?)\)/ ) { 
    320             $crit = $1; 
    321         } 
    322         if ( $theSort eq 'nocase' ) { 
    323             $crit = uc($crit); 
    324         } 
    325         $crit =~ s/[^$Foswiki::regex{'mixedAlphaNum'}]//go; 
    326  
    327         my $group = $crit; 
    328         $group = substr( $crit, 0, 1 ) unless $theSort eq 'num'; 
    329  
    330         my $itemFormat = $theFormat; 
    331         if ( $thePattern && $item =~ m/$thePattern/ ) { 
    332             my $arg1  = $1; 
    333             my $arg2  = $2; 
    334             my $arg3  = $3; 
    335             my $arg4  = $4; 
    336             my $arg5  = $5; 
    337             my $arg6  = $6; 
    338             my $arg7  = $7; 
    339             my $arg8  = $8; 
    340             my $arg9  = $9; 
    341             my $arg10 = $10; 
    342  
    343             $arg1  = '' unless defined $arg1; 
    344             $arg2  = '' unless defined $arg2; 
    345             $arg3  = '' unless defined $arg3; 
    346             $arg4  = '' unless defined $arg4; 
    347             $arg5  = '' unless defined $arg5; 
    348             $arg6  = '' unless defined $arg6; 
    349             $arg7  = '' unless defined $arg7; 
    350             $arg8  = '' unless defined $arg8; 
    351             $arg9  = '' unless defined $arg9; 
    352             $arg10 = '' unless defined $arg10; 
    353  
    354             $item = $arg1 if $arg1; 
    355             $itemFormat =~ s/\$10/$arg10/g; 
    356             $itemFormat =~ s/\$1/$arg1/g; 
    357             $itemFormat =~ s/\$2/$arg2/g; 
    358             $itemFormat =~ s/\$3/$arg3/g; 
    359             $itemFormat =~ s/\$4/$arg4/g; 
    360             $itemFormat =~ s/\$5/$arg5/g; 
    361             $itemFormat =~ s/\$6/$arg6/g; 
    362             $itemFormat =~ s/\$7/$arg7/g; 
    363             $itemFormat =~ s/\$8/$arg8/g; 
    364             $itemFormat =~ s/\$9/$arg9/g; 
    365         } 
    366  
    367         my %descriptor = ( 
    368             crit   => $crit, 
    369             item   => $item, 
    370             group  => $group, 
    371             format => $itemFormat, 
     425 
     426        my $groupFormat = expandVariables($theGroup, 
     427          anchor=>$anchor, 
     428          group=>$group, 
     429          cont=>$cont, 
     430          index=>$listIndex+1, 
     431          count=>$listSize, 
     432          col=>$colIndex, 
     433          row=>$rowIndex, 
     434          item=>$item, 
    372435        ); 
    373  
    374 #writeDebug("group=$descriptor{group}, item=$descriptor{item} crit=$descriptor{crit}"); 
    375         push @theList, \%descriptor; 
    376     } 
    377  
    378     my $listSize = scalar(@theList); 
    379     return '' unless $listSize; 
    380  
    381     # sort it 
    382     @theList = sort { $a->{crit} cmp $b->{crit} } @theList 
    383       if $theSort =~ /nocase|on/; 
    384     @theList = sort { $a->{crit} <=> $b->{crit} } @theList if $theSort eq 'num'; 
    385     @theList = reverse @theList if $theReverse eq 'on'; 
    386  
    387     my $result = 
    388       "<table class='fltLayoutTable' cellspacing='0' cellpadding='0'>\n<tr>\n"; 
    389  
    390   # - a col should at least contain a single group letter and one additional row 
    391     my $colSize = ceil( $listSize / $maxCols ); 
    392  
    393     #writeDebug("maxCols=$maxCols, colSize=$colSize, listSize=$listSize"); 
    394  
    395     my $listIndex  = 0; 
    396     my $insideList = 0; 
    397     my $itemIndex  = 0; 
    398     my $group      = ''; 
    399     my @anchors    = (); 
    400  
    401     foreach my $colIndex ( 1 .. $maxCols ) { 
    402         $result .= "  <td valign='top'>\n"; 
    403  
    404         #writeDebug("new col"); 
    405         my $rowIndex = 1; 
    406         while (1) { 
    407             my $descriptor = $theList[$listIndex]; 
    408             my $format     = $$descriptor{format}; 
    409             my $item       = $$descriptor{item}; 
    410  
    411 #writeDebug("listIndex=$listIndex, itemIndex=$itemIndex, colIndex=$colIndex, rowIndex=$rowIndex, item=$item, format=$format"); 
    412  
    413             # construct group format 
    414             my $thisGroup = $$descriptor{group}; 
    415             my $cont      = ''; 
    416             if ( ( $theGroup && $group ne $thisGroup ) || $rowIndex == 1 ) { 
    417  
    418 #last if $itemIndex % $colSize < 2 && $colIndex < $maxCols; # prevent schusterjunge 
    419  
    420                 if ( $thisGroup eq $group && $rowIndex == 1 ) { 
    421                     $cont = " <span class='fltCont'>(cont.)</span>"; 
    422                 } 
    423                 else { 
    424                     $group = $thisGroup; 
    425                 } 
    426  
    427                 if ($insideList) { 
    428                     $result .= "</ul>\n"; 
    429                     $insideList = 0; 
    430                 } 
    431  
    432                 # create an anchor to this group 
    433                 my $anchor = ''; 
    434                 if ( $theGroup =~ /\$anchor/ ) { 
    435                     $anchor = getAnchorName( $session, $group ); 
    436                     if ($anchor) { 
    437                         push @anchors, 
    438                           { 
    439                             name  => $anchor, 
    440                             title => $group, 
    441                           }; 
    442                         $anchor = "<a class='fltAnchor' name='$anchor'></a>"; 
    443                     } 
    444                 } 
    445  
    446                 my $groupFormat = $theGroup; 
    447                 expandVariables( 
    448                     $groupFormat, 
    449                     anchor => $anchor, 
    450                     group  => $group, 
    451                     cont   => $cont, 
    452                     index  => $listIndex + 1, 
    453                     count  => $listSize, 
    454                     col    => $colIndex, 
    455                     row    => $rowIndex, 
    456                     item   => $item, 
    457                 ); 
    458                 $result .= $groupFormat; 
    459             } 
    460  
    461             # construct line 
    462             my $text = "  <li>$format</li>\n"; 
    463             expandVariables( 
    464                 $text, 
    465                 group => $group, 
    466                 cont  => '', 
    467                 index => $listIndex + 1, 
    468                 count => $listSize, 
    469                 col   => $colIndex, 
    470                 row   => $rowIndex, 
    471                 item  => $item, 
    472             ); 
    473  
    474             unless ($insideList) { 
    475                 $insideList = 1; 
    476                 $result .= "  <ul>\n"; 
    477             } 
    478  
    479             # add to result 
    480             $result .= $text; 
    481  
    482             # keep track if indexes 
    483             $listIndex++; 
    484             $itemIndex++; 
    485             $rowIndex++; 
    486             last unless $itemIndex % $colSize && $listIndex < $listSize; 
    487         } 
    488         if ($insideList) { 
    489             $result .= "  </ul>\n"; 
    490             $insideList = 0; 
    491         } 
    492         $result .= "</td>\n"; 
    493         last unless $listIndex < $listSize; 
    494     } 
    495     $result .= "</tr>\n</table>"; 
    496  
    497     my $anchors = ''; 
    498     if ( @anchors > $theAnchorThreshold ) { 
    499         if ( $theHeader =~ /\$anchors/ || $theFooter =~ /\$anchors/ ) { 
    500             $anchors = "<div class='fltAnchors'>" 
    501               . join( ' ', 
    502                 map( "<a href='#$_->{name}'>$_->{title}</a>", @anchors ) ) 
    503               . '</div>'; 
    504         } 
    505     } 
    506  
    507     #writeDebug("anchors=$anchors"); 
    508  
    509     expandVariables( $theHeader, count => $listSize, anchors => $anchors ); 
    510     expandVariables( $theFooter, count => $listSize, anchors => $anchors ); 
    511  
    512     $result = Foswiki::Func::expandCommonVariables( 
    513         "<div class='fltMakeIndexWrapper'>" 
    514           . $theHeader 
    515           . $result 
    516           . $theFooter 
    517           . "</div>", 
    518         $theTopic, $theWeb 
    519     ); 
    520  
    521     #writeDebug("result=$result"); 
    522  
    523     # count MAKEINDEX calls 
    524     $makeIndexCounter++; 
    525  
    526     return $result; 
     436        $result .= $groupFormat; 
     437      } 
     438 
     439      # construct line 
     440      my $text = expandVariables("  <li>$format</li>\n", 
     441        group=>$group, 
     442        cont=>'', 
     443        index=>$listIndex+1, 
     444        count=>$listSize, 
     445        col=>$colIndex, 
     446        row=>$rowIndex, 
     447        item=>$item, 
     448      ); 
     449 
     450      unless ($insideList) { 
     451        $insideList = 1; 
     452        $result .= "  <ul>\n"; 
     453      } 
     454 
     455      # add to result 
     456      $result .= $text; 
     457 
     458      # keep track if indexes 
     459      $listIndex++; 
     460      $itemIndex++; 
     461      $rowIndex++; 
     462      last unless $itemIndex % $colSize && $listIndex < $listSize; 
     463    } 
     464    if ($insideList) { 
     465      $result .= "  </ul>\n"; 
     466      $insideList = 0; 
     467    } 
     468    $result .= "</td>\n"; 
     469    last unless $listIndex < $listSize; 
     470  } 
     471  $result .= "</tr>\n</table>"; 
     472 
     473  my $anchors = ''; 
     474  if (@anchors > $theAnchorThreshold) { 
     475    if ($theHeader =~ /\$anchors/ || $theFooter =~ /\$anchors/) { 
     476      $anchors =  
     477        "<div class='fltAnchors'>". 
     478        join(' ',  
     479          map("<a href='#$_->{name}'>$_->{title}</a>", @anchors) 
     480        ). 
     481        '</div>'; 
     482    } 
     483  } 
     484  #writeDebug("anchors=$anchors"); 
     485 
     486  $result =  
     487    "<div class='fltMakeIndexWrapper'>". 
     488      expandVariables($theHeader, count=>$listSize, anchors=>$anchors). 
     489      $result. 
     490      expandVariables($theFooter, count=>$listSize, anchors=>$anchors). 
     491    "</div>"; 
     492  #writeDebug("result=$result"); 
     493 
     494  # count MAKEINDEX calls 
     495  $this->{makeIndexCounter}++; 
     496 
     497  return $result; 
    527498} 
    528499 
    529500############################################################################### 
    530501sub handleFormatList { 
    531     my ( $session, $params, $theTopic, $theWeb ) = @_; 
    532  
    533     #writeDebug("handleFormatList(".$params->stringify().")"); 
    534  
    535     my $theList = $params->{_DEFAULT}; 
    536     $theList = $params->{list} unless defined $theList; 
    537     $theList = '' unless defined $theList; 
    538  
    539     my $thePattern = $params->{pattern} || '^\s*(.*?)\s*$'; 
    540     my $theFormat  = $params->{format}; 
    541     my $theHeader  = $params->{header} || ''; 
    542     my $theFooter  = $params->{footer} || ''; 
    543     my $theSplit   = $params->{split}; 
    544     $theSplit = '[,\s]+' unless defined $theSplit; 
    545     my $theSeparator  = $params->{separator}; 
    546     my $theLimit      = $params->{limit} || -1; 
    547     my $theSkip       = $params->{skip} || 0; 
    548     my $theSort       = $params->{sort} || 'off'; 
    549     my $theUnique     = $params->{unique} || ''; 
    550     my $theExclude    = $params->{exclude} || ''; 
    551     my $theInclude    = $params->{include} || ''; 
    552     my $theReverse    = $params->{reverse} || ''; 
    553     my $theSelection  = $params->{selection}; 
    554     my $theMarker     = $params->{marker}; 
    555     my $theMap        = $params->{map}; 
    556     my $theNullFormat = $params->{null} || ''; 
    557     my $theTokenize   = $params->{tokenize}; 
    558     my $theHideEmpty  = Foswiki::Func::isTrue( $params->{hideempty}, 1 ); 
    559  
    560     $theFormat = '$1' unless defined $theFormat; 
    561  
    562     $theMarker    = ' selected ' unless defined $theMarker; 
    563     $theSeparator = ', '         unless defined $theSeparator; 
    564  
    565     $theList = 
    566       Foswiki::Func::expandCommonVariables( $theList, $theTopic, $theWeb ) 
    567       if expandVariables($theList); 
    568  
    569     #writeDebug("theList='$theList'"); 
    570     #writeDebug("thePattern='$thePattern'"); 
    571     #writeDebug("theFormat='$theFormat'"); 
    572     #writeDebug("theSplit='$theSplit'"); 
    573     #writeDebug("theSeparator='$theSeparator'"); 
    574     #writeDebug("theLimit='$theLimit'"); 
    575     #writeDebug("theSkip='$theSkip'"); 
    576     #writeDebug("theSort='$theSort'"); 
    577     #writeDebug("theUnique='$theUnique'"); 
    578     #writeDebug("theExclude='$theExclude'"); 
    579     #writeDebug("theInclude='$theInclude'"); 
    580  
    581     my %map = (); 
    582     if ($theMap) { 
    583         %map = 
    584           map { $_ =~ /^(.*)=(.*)$/, $1 => $2 } split( /\s*,\s*/, $theMap ); 
    585     } 
    586  
    587     my %tokens  = (); 
    588     my $tokenNr = 0; 
    589     if ($theTokenize) { 
    590         $theList =~ 
    591 s/($theTokenize)/$tokenNr++; $tokens{'token_'.$tokenNr} = $1; 'token_'.$tokenNr/gems; 
    592     } 
    593  
    594     my @theList = split( /$theSplit/, $theList ); 
    595  
    596     if ($theTokenize) { 
    597         @theList = map { ( defined $tokens{$_} ) ? $tokens{$_} : $_ } @theList; 
    598     } 
    599  
    600     if ( $theSort ne 'off' ) { 
    601         if ( $theSort eq 'alpha' || $theSort eq 'on' ) { 
    602             @theList = sort { uc($a) cmp uc($b) } @theList; 
    603         } 
    604         elsif ( $theSort eq 'num' ) { 
    605             @theList = sort { $a <=> $b } @theList; 
    606         } 
    607     } 
    608     @theList = reverse @theList if $theReverse eq 'on'; 
    609  
    610     my %seen = (); 
    611     my @result; 
    612     my $count = 0; 
    613     my $skip  = $theSkip; 
     502  my ($this, $params, $theTopic, $theWeb) = @_; 
     503   
     504  #writeDebug("handleFormatList(".$params->stringify().")"); 
     505 
     506  my $theList = $params->{_DEFAULT}; 
     507  $theList = $params->{list} unless defined $theList; 
     508  $theList = '' unless defined $theList; 
     509 
     510  my $thePattern = $params->{pattern} || '^\s*(.*?)\s*$'; 
     511  my $theFormat = $params->{format}; 
     512  my $theHeader = $params->{header} || ''; 
     513  my $theFooter = $params->{footer} || ''; 
     514  my $theSplit = $params->{split}; 
     515  my $theSeparator = $params->{separator}; 
     516  my $theLimit = $params->{limit} || -1;  
     517  my $theSkip = $params->{skip} || 0;  
     518  my $theSort = $params->{sort} || 'off'; 
     519  my $theUnique = $params->{unique} || ''; 
     520  my $theExclude = $params->{exclude} || ''; 
     521  my $theInclude = $params->{include} || ''; 
     522  my $theReverse = $params->{reverse} || ''; 
     523  my $theSelection = $params->{selection}; 
     524  my $theMarker = $params->{marker}; 
     525  my $theMap = $params->{map}; 
     526  my $theNullFormat = $params->{null} || ''; 
     527  my $theTokenize = $params->{tokenize}; 
     528  my $theHideEmpty = Foswiki::Func::isTrue($params->{hideempty}, 1); 
     529  my $theReplace = $params->{replace}; 
     530 
     531  $theFormat = '$1' unless defined $theFormat; 
     532  $theSplit = '\s*,\s*' unless defined $theSplit; 
     533  $theMarker = ' selected ' unless defined $theMarker; 
     534  $theSeparator = ', ' unless defined $theSeparator; 
     535 
     536  $theList = expandVariables($theList); 
     537 
     538  #writeDebug("theList='$theList'"); 
     539  #writeDebug("thePattern='$thePattern'"); 
     540  #writeDebug("theFormat='$theFormat'"); 
     541  #writeDebug("theSplit='$theSplit'"); 
     542  #writeDebug("theSeparator='$theSeparator'"); 
     543  #writeDebug("theLimit='$theLimit'"); 
     544  #writeDebug("theSkip='$theSkip'"); 
     545  #writeDebug("theSort='$theSort'"); 
     546  #writeDebug("theUnique='$theUnique'"); 
     547  #writeDebug("theExclude='$theExclude'"); 
     548  #writeDebug("theInclude='$theInclude'"); 
     549 
     550  my %map = (); 
     551  if ($theMap) { 
     552    %map = map {$_ =~ /^(.*)=(.*)$/, $1=>$2} split(/\s*,\s*/, $theMap); 
     553  } 
     554 
     555  my %tokens = (); 
     556  my $tokenNr = 0; 
     557  if ($theTokenize) { 
     558    $theList =~ s/($theTokenize)/$tokenNr++; $tokens{'token_'.$tokenNr} = $1; 'token_'.$tokenNr/gems; 
     559  } 
     560 
     561  my @theList = split(/$theSplit/, $theList); 
     562 
     563  if ($theReplace) { 
     564    my %replace = map {$_ =~ /^(.*)=(.*)$/, $1=>$2} split(/\s*,\s*/, $theReplace); 
     565     
    614566    foreach my $item (@theList) { 
    615  
    616         #writeDebug("found '$item'"); 
    617         next if $theExclude && $item =~ /^($theExclude)$/; 
    618         next if $theInclude && $item !~ /^($theInclude)$/; 
    619         next if $item =~ /^$/;    # skip empty elements 
    620         my $arg1  = ''; 
    621         my $arg2  = ''; 
    622         my $arg3  = ''; 
    623         my $arg4  = ''; 
    624         my $arg5  = ''; 
    625         my $arg6  = ''; 
    626         my $arg7  = ''; 
    627         my $arg8  = ''; 
    628         my $arg9  = ''; 
    629         my $arg10 = ''; 
    630         if ( $item =~ m/$thePattern/ ) { 
    631             $arg1  = $1; 
    632             $arg2  = $2; 
    633             $arg3  = $3; 
    634             $arg4  = $4; 
    635             $arg5  = $5; 
    636             $arg6  = $6; 
    637             $arg7  = $7; 
    638             $arg8  = $8; 
    639             $arg9  = $9; 
    640             $arg10 = $10; 
    641  
    642             $arg1  = '' unless defined $arg1; 
    643             $arg2  = '' unless defined $arg2; 
    644             $arg3  = '' unless defined $arg3; 
    645             $arg4  = '' unless defined $arg4; 
    646             $arg5  = '' unless defined $arg5; 
    647             $arg6  = '' unless defined $arg6; 
    648             $arg7  = '' unless defined $arg7; 
    649             $arg8  = '' unless defined $arg8; 
    650             $arg9  = '' unless defined $arg9; 
    651             $arg10 = '' unless defined $arg10; 
    652         } 
    653         else { 
    654             next; 
    655         } 
    656         my $line = $theFormat; 
    657         $line =~ s/\$10/$arg10/g; 
    658         $line =~ s/\$1/$arg1/g; 
    659         $line =~ s/\$2/$arg2/g; 
    660         $line =~ s/\$3/$arg3/g; 
    661         $line =~ s/\$4/$arg4/g; 
    662         $line =~ s/\$5/$arg5/g; 
    663         $line =~ s/\$6/$arg6/g; 
    664         $line =~ s/\$7/$arg7/g; 
    665         $line =~ s/\$8/$arg8/g; 
    666         $line =~ s/\$9/$arg9/g; 
    667         $line =~ s/\$map\((.*?)\)/($map{$1}||$1)/ge; 
    668  
    669         #writeDebug("after susbst '$line'"); 
    670         if ( $theUnique eq 'on' ) { 
    671             next if $seen{$line}; 
    672             $seen{$line} = 1; 
    673         } 
    674  
    675         $line =~ s/\$index/$count+1/ge; 
    676         if ( $theSelection && $item =~ /$theSelection/ ) { 
    677             $line =~ s/\$marker/$theMarker/g; 
    678         } 
    679         else { 
    680             $line =~ s/\$marker//go; 
    681         } 
    682         if ( $skip-- <= 0 ) { 
    683             push @result, $line unless ( $theHideEmpty && $line eq '' ); 
    684             $count++; 
    685             last if $theLimit - $count == 0; 
    686         } 
    687     } 
    688  
    689     #writeDebug("count=$count"); 
    690     my $result = ''; 
    691     if ( $count == 0 ) { 
    692         return '' unless $theNullFormat; 
    693         $result = $theNullFormat; 
    694     } 
    695     else { 
    696         $result = join( $theSeparator, @result ); 
    697     } 
    698  
    699     $result = $theHeader . $result . $theFooter; 
    700     $result =~ s/\$count/$count/g; 
    701     $result = 
    702       Foswiki::Func::expandCommonVariables( $result, $theTopic, $theWeb ) 
    703       if expandVariables($result); 
    704  
    705     #writeDebug("result=$result"); 
    706  
    707     return $result; 
     567      foreach my $pattern (keys %replace) { 
     568        $item =~ s/$pattern/$replace{$pattern}/g; 
     569      } 
     570    } 
     571  } 
     572 
     573 
     574  if ($theTokenize && $tokenNr) { 
     575    foreach my $item (@theList) { 
     576      foreach my $token (keys %tokens) { 
     577        $item =~ s/$token/$tokens{$token}/g; 
     578      } 
     579    } 
     580  } 
     581 
     582  if ($theSort ne 'off') { 
     583    if ($theSort eq 'alpha' || $theSort eq 'on') { 
     584      @theList = sort {uc($a) cmp uc($b)} @theList; 
     585    } elsif ($theSort eq 'num') { 
     586      @theList = sort {$a <=> $b} @theList; 
     587    } 
     588  } 
     589  @theList = reverse @theList if $theReverse eq 'on'; 
     590 
     591  my %seen = (); 
     592  my @result; 
     593  my $count = 0; 
     594  my $skip = $theSkip; 
     595  foreach my $item (@theList) { 
     596    #writeDebug("found '$item'"); 
     597    next if $theExclude && $item =~ /^($theExclude)$/; 
     598    next if $theInclude && $item !~ /^($theInclude)$/; 
     599    next if $item =~ /^$/; # skip empty elements 
     600    my $arg1 = ''; 
     601    my $arg2 = ''; 
     602    my $arg3 = ''; 
     603    my $arg4 = ''; 
     604    my $arg5 = ''; 
     605    my $arg6 = ''; 
     606    my $arg7 = ''; 
     607    my $arg8 = ''; 
     608    my $arg9 = ''; 
     609    my $arg10 = ''; 
     610    if ($item =~ m/$thePattern/) { 
     611      $arg1 = $1; 
     612      $arg2 = $2; 
     613      $arg3 = $3; 
     614      $arg4 = $4; 
     615      $arg5 = $5; 
     616      $arg6 = $6; 
     617      $arg7 = $7; 
     618      $arg8 = $8; 
     619      $arg9 = $9; 
     620      $arg10 = $10; 
     621 
     622      $arg1 = '' unless defined $arg1; 
     623      $arg2 = '' unless defined $arg2; 
     624      $arg3 = '' unless defined $arg3; 
     625      $arg4 = '' unless defined $arg4; 
     626      $arg5 = '' unless defined $arg5; 
     627      $arg6 = '' unless defined $arg6; 
     628      $arg7 = '' unless defined $arg7; 
     629      $arg8 = '' unless defined $arg8; 
     630      $arg9 = '' unless defined $arg9; 
     631      $arg10 = '' unless defined $arg10; 
     632    } else { 
     633      next; 
     634    } 
     635    my $line = $theFormat; 
     636    $line =~ s/\$10/$arg10/g; 
     637    $line =~ s/\$1/$arg1/g; 
     638    $line =~ s/\$2/$arg2/g; 
     639    $line =~ s/\$3/$arg3/g; 
     640    $line =~ s/\$4/$arg4/g; 
     641    $line =~ s/\$5/$arg5/g; 
     642    $line =~ s/\$6/$arg6/g; 
     643    $line =~ s/\$7/$arg7/g; 
     644    $line =~ s/\$8/$arg8/g; 
     645    $line =~ s/\$9/$arg9/g; 
     646    $line =~ s/\$map\((.*?)\)/($map{$1}||$1)/ge; 
     647    #writeDebug("after susbst '$line'"); 
     648    if ($theUnique eq 'on') { 
     649      next if $seen{$line}; 
     650      $seen{$line} = 1; 
     651    } 
     652 
     653    $line =~ s/\$index/$count+1/ge; 
     654    if ($theSelection && $item =~ /$theSelection/) { 
     655      $line =~ s/\$marker/$theMarker/g  
     656    } else { 
     657      $line =~ s/\$marker//go; 
     658    } 
     659    if ($skip-- <= 0) { 
     660      push @result, $line unless ($theHideEmpty && $line eq ''); 
     661      $count++; 
     662      last if $theLimit - $count == 0; 
     663    } 
     664  } 
     665  #writeDebug("count=$count"); 
     666  my $result = ''; 
     667  if ($count == 0) { 
     668    return '' unless $theNullFormat; 
     669    $result = $theNullFormat; 
     670  } else { 
     671    $result = join($theSeparator, @result); 
     672  } 
     673 
     674  $result = $theHeader.$result.$theFooter; 
     675  $result =~ s/\$count/$count/g; 
     676 
     677  return expandVariables($result); 
    708678} 
    709679 
    710680############################################################################### 
    711681sub getAnchorName { 
    712     my ( $session, $text ) = @_; 
    713  
    714     $text = $text . '_' . $makeIndexCounter; 
    715     return '' if $seenAnchorNames{$text}; 
    716     $seenAnchorNames{$text} = 1; 
    717  
    718     if ( $Foswiki::Plugins::VERSION > 2.0 ) { 
    719         require Foswiki::Render::Anchors; 
    720         my $anchor = Foswiki::Render::Anchors::make($text); 
    721         return Foswiki::urlEncode($anchor); 
    722     } 
    723     else { 
    724         return $session->renderer->makeAnchorName($text); 
    725     } 
     682  my ($this, $text) = @_; 
     683 
     684  $text = $text.'_'.$this->{makeIndexCounter}; 
     685  return '' if $this->{seenAnchorNames}{$text}; 
     686  $this->{seenAnchorNames}{$text} = 1; 
     687 
     688  if ($Foswiki::Plugins::VERSION > 2.0) { 
     689    require Foswiki::Render::Anchors; 
     690    my $anchor = Foswiki::Render::Anchors::make($text); 
     691    return Foswiki::urlEncode($anchor); 
     692  } else { 
     693    return $this->{session}->renderer->makeAnchorName($text); 
     694  } 
    726695} 
    727696 
    728697############################################################################### 
    729698sub expandVariables { 
    730     my ( $text, %params ) = @_; 
    731  
    732     return 0 unless $text; 
    733  
    734     my $found = 0; 
    735  
    736     foreach my $key ( keys %params ) { 
    737         $found = 1 if $text =~ s/\$$key\b/$params{$key}/g; 
    738     } 
    739  
    740     $found = 1 if $text =~ s/\$perce?nt/\%/go; 
    741     $found = 1 if $text =~ s/\$nop//go; 
    742     $found = 1 if $text =~ s/\$n/\n/go; 
    743     $found = 1 if $text =~ s/\$dollar/\$/go; 
    744  
    745     $_[0] = $text if $found; 
    746  
    747     return $found; 
    748 } 
    749  
    750 ############################################################################### 
    751 sub showError { 
    752     my ($errormessage) = @_; 
    753     return "<font size=\"-1\" color=\"#FF0000\">$errormessage</font>"; 
    754 } 
     699  my ($text, %params) = @_; 
     700 
     701  if ($text) { 
     702 
     703    foreach my $key (keys %params) { 
     704      $text =~ s/\$$key\b/$params{$key}/g; 
     705    } 
     706 
     707    $text =~ s/\$perce?nt/\%/go; 
     708    $text =~ s/\$nop//go; 
     709    $text =~ s/\$n/\n/go; 
     710    $text =~ s/\$dollar/\$/go; 
     711 
     712  } 
     713 
     714  return $text; 
     715} 
     716 
     717############################################################################### 
     718sub inlineError { 
     719  return "<span class='foswikiAlert'>".$_[0]."</span>"; 
     720} 
     721 
     722############################################################################### 
     723sub writeDebug { 
     724  print STDERR "- FilterPlugin - $_[0]\n" if DEBUG; 
     725} 
     726 
    755727 
    7567281; 
  • trunk/FilterPlugin/lib/Foswiki/Plugins/FilterPlugin/build.pl

    r14680 r14711  
    44# 
    55BEGIN { 
    6     foreach my $pc ( split( /:/, $ENV{FOSWIKI_LIBS} ) ) { 
    7         unshift @INC, $pc; 
    8     } 
     6  foreach my $pc (split(/:/, $ENV{FOSWIKI_LIBS})) { 
     7    unshift @INC, $pc; 
     8  } 
    99} 
    1010 
     
    1212 
    1313# Create the build object 
    14 $build = new Foswiki::Contrib::Build('FilterPlugin'); 
     14$build = new Foswiki::Contrib::Build( 'FilterPlugin' ); 
    1515 
    1616# Build the target on the command line, or the default target 
    17 $build->build( $build->{target} ); 
     17$build->build($build->{target}); 
    1818 
Note: See TracChangeset for help on using the changeset viewer.