source: trunk/FilterPlugin/lib/Foswiki/Plugins/FilterPlugin/Core.pm @ 14767

Revision 14767, 20.9 KB checked in by MichaelDaum, 13 months ago (diff)

Item11829: fixed lists not being processed properly before iterating over them

  • Property svn:keywords set to Revision Date
Line 
1# Plugin for Foswiki - The Free and Open Source Wiki, http://foswiki.org/
2#
3# Copyright (C) 2005-2012 Michael Daum http://michaeldaumconsulting.com
4#
5# This program is free software; you can redistribute it and/or
6# modify it under the terms of the GNU General Public License
7# as published by the Free Software Foundation; either version 2
8# of the License, or (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details, published at
14# http://www.gnu.org/copyleft/gpl.html
15#
16###############################################################################
17
18package Foswiki::Plugins::FilterPlugin::Core;
19
20use strict;
21use warnings;
22
23use POSIX qw(ceil);
24use Foswiki::Plugins();
25use Foswiki::Func();
26
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;
43}
44
45###############################################################################
46sub handleFilterArea {
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);
54}
55
56###############################################################################
57# filter a topic or url thru a regular expression
58# attributes
59#    * pattern
60#    * format
61#    * hits
62#    * topic
63#    * expand
64#
65sub handleFilter {
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  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 = Foswiki::Func::expandCommonVariables($theList, $theTopic, $theWeb)
284    if expandVariables($theList);
285
286  #writeDebug("theList=$theList");
287
288  # create the item descriptors for each list item
289  my @theList = ();
290  my %seen = ();
291  foreach my $item (split(/$theSplit/, $theList)) {
292    next if $theExclude && $item =~ /^($theExclude)$/;
293    next if $theInclude && $item !~ /^($theInclude)$/;
294
295    $item =~ s/<nop>//go;
296    $item =~ s/^\s+//go;
297    $item =~ s/\s+$//go;
298    next unless $item;
299
300    #writeDebug("item='$item'");
301
302    if ($theUnique) {
303      next if $seen{$item};
304      $seen{$item} = 1;
305    }
306
307    my $crit = $item;
308    if ($crit =~ /\((.*?)\)/) {
309      $crit = $1;
310    }
311    if ($theSort eq 'nocase') {
312      $crit = uc($crit);
313    }
314    $crit =~ s/[^$Foswiki::regex{'mixedAlphaNum'}]//go;
315
316    my $group = $crit;
317    $group = substr($crit, 0, 1) unless $theSort eq 'num';
318
319    my $itemFormat = $theFormat;
320    if ($thePattern && $item =~ m/$thePattern/) {
321      my $arg1 = $1;
322      my $arg2 = $2;
323      my $arg3 = $3;
324      my $arg4 = $4;
325      my $arg5 = $5;
326      my $arg6 = $6;
327      my $arg7 = $7;
328      my $arg8 = $8;
329      my $arg9 = $9;
330      my $arg10 = $10;
331
332      $arg1 = '' unless defined $arg1;
333      $arg2 = '' unless defined $arg2;
334      $arg3 = '' unless defined $arg3;
335      $arg4 = '' unless defined $arg4;
336      $arg5 = '' unless defined $arg5;
337      $arg6 = '' unless defined $arg6;
338      $arg7 = '' unless defined $arg7;
339      $arg8 = '' unless defined $arg8;
340      $arg9 = '' unless defined $arg9;
341      $arg10 = '' unless defined $arg10;
342
343      $item = $arg1 if $arg1;
344      $itemFormat =~ s/\$10/$arg10/g;
345      $itemFormat =~ s/\$1/$arg1/g;
346      $itemFormat =~ s/\$2/$arg2/g;
347      $itemFormat =~ s/\$3/$arg3/g;
348      $itemFormat =~ s/\$4/$arg4/g;
349      $itemFormat =~ s/\$5/$arg5/g;
350      $itemFormat =~ s/\$6/$arg6/g;
351      $itemFormat =~ s/\$7/$arg7/g;
352      $itemFormat =~ s/\$8/$arg8/g;
353      $itemFormat =~ s/\$9/$arg9/g;
354    }
355
356    my %descriptor = (
357      crit=>$crit,
358      item=>$item,
359      group=>$group,
360      format=>$itemFormat,
361    );
362    #writeDebug("group=$descriptor{group}, item=$descriptor{item} crit=$descriptor{crit}");
363    push @theList, \%descriptor;
364  }
365
366  my $listSize = scalar(@theList);
367  return '' unless $listSize;
368
369  # sort it
370  @theList = sort {$a->{crit} cmp $b->{crit}} @theList if $theSort =~ /nocase|on/;
371  @theList = sort {$a->{crit} <=> $b->{crit}} @theList if $theSort eq 'num';
372  @theList = reverse @theList if $theReverse eq 'on';
373
374  my $result = "<table class='fltLayoutTable' cellspacing='0' cellpadding='0'>\n<tr>\n";
375
376  # - a col should at least contain a single group letter and one additional row
377  my $colSize = ceil($listSize / $maxCols);
378  #writeDebug("maxCols=$maxCols, colSize=$colSize, listSize=$listSize");
379
380  my $listIndex = 0;
381  my $insideList = 0;
382  my $itemIndex = 0;
383  my $group = '';
384  my @anchors = ();
385
386  foreach my $colIndex (1..$maxCols) {
387    $result .= "  <td valign='top'>\n";
388
389    #writeDebug("new col");
390    my $rowIndex = 1;
391    while (1) {
392      my $descriptor = $theList[$listIndex];
393      my $format = $$descriptor{format};
394      my $item = $$descriptor{item};
395      #writeDebug("listIndex=$listIndex, itemIndex=$itemIndex, colIndex=$colIndex, rowIndex=$rowIndex, item=$item, format=$format");
396
397      # construct group format
398      my $thisGroup = $$descriptor{group};
399      my $cont = '';
400      if (($theGroup && $group ne $thisGroup) || $rowIndex == 1) {
401        #last if $itemIndex % $colSize < 2 && $colIndex < $maxCols; # prevent schusterjunge
402
403        if ($thisGroup eq $group && $rowIndex == 1) {
404          $cont = " <span class='fltCont'>(cont.)</span>";
405        } else {
406          $group = $thisGroup;
407        }
408
409        if ($insideList) {
410          $result .= "</ul>\n";
411          $insideList = 0;
412        }
413
414        # create an anchor to this group
415        my $anchor = '';
416        if ($theGroup =~ /\$anchor/) {
417          $anchor = $this->getAnchorName($group);
418          if ($anchor)  {
419            push @anchors, {
420              name=>$anchor,
421              title=>$group,
422            };
423            $anchor = "<a class='fltAnchor' name='$anchor'></a>";
424          }
425        }
426
427        my $groupFormat = $theGroup;
428        expandVariables($groupFormat,
429          anchor=>$anchor,
430          group=>$group,
431          cont=>$cont,
432          index=>$listIndex+1,
433          count=>$listSize,
434          col=>$colIndex,
435          row=>$rowIndex,
436          item=>$item,
437        );
438        $result .= $groupFormat;
439      }
440
441      # construct line
442      my $text = "  <li>$format</li>\n";
443      expandVariables($text,
444        group=>$group,
445        cont=>'',
446        index=>$listIndex+1,
447        count=>$listSize,
448        col=>$colIndex,
449        row=>$rowIndex,
450        item=>$item,
451      );
452
453      unless ($insideList) {
454        $insideList = 1;
455        $result .= "  <ul>\n";
456      }
457
458      # add to result
459      $result .= $text;
460
461      # keep track if indexes
462      $listIndex++;
463      $itemIndex++;
464      $rowIndex++;
465      last unless $itemIndex % $colSize && $listIndex < $listSize;
466    }
467    if ($insideList) {
468      $result .= "  </ul>\n";
469      $insideList = 0;
470    }
471    $result .= "</td>\n";
472    last unless $listIndex < $listSize;
473  }
474  $result .= "</tr>\n</table>";
475
476  my $anchors = '';
477  if (@anchors > $theAnchorThreshold) {
478    if ($theHeader =~ /\$anchors/ || $theFooter =~ /\$anchors/) {
479      $anchors = 
480        "<div class='fltAnchors'>".
481        join(' ', 
482          map("<a href='#$_->{name}'>$_->{title}</a>", @anchors)
483        ).
484        '</div>';
485    }
486  }
487  #writeDebug("anchors=$anchors");
488  expandVariables($theHeader, count=>$listSize, anchors=>$anchors);
489  expandVariables($theFooter, count=>$listSize, anchors=>$anchors);
490
491  $result = 
492    "<div class='fltMakeIndexWrapper'>".
493      $theHeader.
494      $result.
495      $theFooter.
496    "</div>";
497  #writeDebug("result=$result");
498
499  # count MAKEINDEX calls
500  $this->{makeIndexCounter}++;
501
502  return $result;
503}
504
505###############################################################################
506sub handleFormatList {
507  my ($this, $params, $theTopic, $theWeb) = @_;
508 
509  #writeDebug("handleFormatList(".$params->stringify().")");
510
511  my $theList = $params->{_DEFAULT};
512  $theList = $params->{list} unless defined $theList;
513  $theList = '' unless defined $theList;
514
515  my $thePattern = $params->{pattern} || '^\s*(.*?)\s*$';
516  my $theFormat = $params->{format};
517  my $theHeader = $params->{header} || '';
518  my $theFooter = $params->{footer} || '';
519  my $theSplit = $params->{split};
520  my $theSeparator = $params->{separator};
521  my $theLimit = $params->{limit} || -1; 
522  my $theSkip = $params->{skip} || 0; 
523  my $theSort = $params->{sort} || 'off';
524  my $theUnique = $params->{unique} || '';
525  my $theExclude = $params->{exclude} || '';
526  my $theInclude = $params->{include} || '';
527  my $theReverse = $params->{reverse} || '';
528  my $theSelection = $params->{selection};
529  my $theMarker = $params->{marker};
530  my $theMap = $params->{map};
531  my $theNullFormat = $params->{null} || '';
532  my $theTokenize = $params->{tokenize};
533  my $theHideEmpty = Foswiki::Func::isTrue($params->{hideempty}, 1);
534  my $theReplace = $params->{replace};
535
536  $theFormat = '$1' unless defined $theFormat;
537  $theSplit = '\s*,\s*' unless defined $theSplit;
538  $theMarker = ' selected ' unless defined $theMarker;
539  $theSeparator = ', ' unless defined $theSeparator;
540
541  $theList = Foswiki::Func::expandCommonVariables($theList, $theTopic, $theWeb)
542    if expandVariables($theList);
543
544  #writeDebug("theList='$theList'");
545  #writeDebug("thePattern='$thePattern'");
546  #writeDebug("theFormat='$theFormat'");
547  #writeDebug("theSplit='$theSplit'");
548  #writeDebug("theSeparator='$theSeparator'");
549  #writeDebug("theLimit='$theLimit'");
550  #writeDebug("theSkip='$theSkip'");
551  #writeDebug("theSort='$theSort'");
552  #writeDebug("theUnique='$theUnique'");
553  #writeDebug("theExclude='$theExclude'");
554  #writeDebug("theInclude='$theInclude'");
555
556  my %map = ();
557  if ($theMap) {
558    %map = map {$_ =~ /^(.*)=(.*)$/, $1=>$2} split(/\s*,\s*/, $theMap);
559  }
560
561  my %tokens = ();
562  my $tokenNr = 0;
563  if ($theTokenize) {
564    $theList =~ s/($theTokenize)/$tokenNr++; $tokens{'token_'.$tokenNr} = $1; 'token_'.$tokenNr/gems;
565  }
566
567  my @theList = split(/$theSplit/, $theList);
568
569  if ($theReplace) {
570    my %replace = map {$_ =~ /^(.*)=(.*)$/, $1=>$2} split(/\s*,\s*/, $theReplace);
571   
572    foreach my $item (@theList) {
573      foreach my $pattern (keys %replace) {
574        $item =~ s/$pattern/$replace{$pattern}/g;
575      }
576    }
577  }
578
579
580  if ($theTokenize && $tokenNr) {
581    foreach my $item (@theList) {
582      foreach my $token (keys %tokens) {
583        $item =~ s/$token/$tokens{$token}/g;
584      }
585    }
586  }
587
588  if ($theSort ne 'off') {
589    if ($theSort eq 'alpha' || $theSort eq 'on') {
590      @theList = sort {uc($a) cmp uc($b)} @theList;
591    } elsif ($theSort eq 'num') {
592      @theList = sort {$a <=> $b} @theList;
593    }
594  }
595  @theList = reverse @theList if $theReverse eq 'on';
596
597  my %seen = ();
598  my @result;
599  my $count = 0;
600  my $skip = $theSkip;
601  foreach my $item (@theList) {
602    #writeDebug("found '$item'");
603    next if $theExclude && $item =~ /^($theExclude)$/;
604    next if $theInclude && $item !~ /^($theInclude)$/;
605    next if $item =~ /^$/; # skip empty elements
606    my $arg1 = '';
607    my $arg2 = '';
608    my $arg3 = '';
609    my $arg4 = '';
610    my $arg5 = '';
611    my $arg6 = '';
612    my $arg7 = '';
613    my $arg8 = '';
614    my $arg9 = '';
615    my $arg10 = '';
616    if ($item =~ m/$thePattern/) {
617      $arg1 = $1;
618      $arg2 = $2;
619      $arg3 = $3;
620      $arg4 = $4;
621      $arg5 = $5;
622      $arg6 = $6;
623      $arg7 = $7;
624      $arg8 = $8;
625      $arg9 = $9;
626      $arg10 = $10;
627
628      $arg1 = '' unless defined $arg1;
629      $arg2 = '' unless defined $arg2;
630      $arg3 = '' unless defined $arg3;
631      $arg4 = '' unless defined $arg4;
632      $arg5 = '' unless defined $arg5;
633      $arg6 = '' unless defined $arg6;
634      $arg7 = '' unless defined $arg7;
635      $arg8 = '' unless defined $arg8;
636      $arg9 = '' unless defined $arg9;
637      $arg10 = '' unless defined $arg10;
638    } else {
639      next;
640    }
641    my $line = $theFormat;
642    $line =~ s/\$10/$arg10/g;
643    $line =~ s/\$1/$arg1/g;
644    $line =~ s/\$2/$arg2/g;
645    $line =~ s/\$3/$arg3/g;
646    $line =~ s/\$4/$arg4/g;
647    $line =~ s/\$5/$arg5/g;
648    $line =~ s/\$6/$arg6/g;
649    $line =~ s/\$7/$arg7/g;
650    $line =~ s/\$8/$arg8/g;
651    $line =~ s/\$9/$arg9/g;
652    $line =~ s/\$map\((.*?)\)/($map{$1}||$1)/ge;
653    #writeDebug("after susbst '$line'");
654    if ($theUnique eq 'on') {
655      next if $seen{$line};
656      $seen{$line} = 1;
657    }
658
659    $line =~ s/\$index/$count+1/ge;
660    if ($theSelection && $item =~ /$theSelection/) {
661      $line =~ s/\$marker/$theMarker/g 
662    } else {
663      $line =~ s/\$marker//go;
664    }
665    if ($skip-- <= 0) {
666      push @result, $line unless ($theHideEmpty && $line eq '');
667      $count++;
668      last if $theLimit - $count == 0;
669    }
670  }
671  #writeDebug("count=$count");
672  my $result = '';
673  if ($count == 0) {
674    return '' unless $theNullFormat;
675    $result = $theNullFormat;
676  } else {
677    $result = join($theSeparator, @result);
678  }
679
680  $result = $theHeader.$result.$theFooter;
681  $result =~ s/\$count/$count/g;
682
683  expandVariables($result);
684  return $result;
685}
686
687###############################################################################
688sub getAnchorName {
689  my ($this, $text) = @_;
690
691  $text = $text.'_'.$this->{makeIndexCounter};
692  return '' if $this->{seenAnchorNames}{$text};
693  $this->{seenAnchorNames}{$text} = 1;
694
695  if ($Foswiki::Plugins::VERSION > 2.0) {
696    require Foswiki::Render::Anchors;
697    my $anchor = Foswiki::Render::Anchors::make($text);
698    return Foswiki::urlEncode($anchor);
699  } else {
700    return $this->{session}->renderer->makeAnchorName($text);
701  }
702}
703
704###############################################################################
705sub expandVariables {
706  my ($text, %params) = @_;
707
708  return 0 unless $text;
709
710  my $found = 0;
711
712  foreach my $key (keys %params) {
713    $found = 1 if $text =~ s/\$$key\b/$params{$key}/g;
714  }
715
716  $found = 1 if $text =~ s/\$perce?nt/\%/go;
717  $found = 1 if $text =~ s/\$nop//go;
718  $found = 1 if $text =~ s/\$n/\n/go;
719  $found = 1 if $text =~ s/\$dollar/\$/go;
720
721  $_[0] = $text if $found;
722
723  return $found;
724}
725
726###############################################################################
727sub inlineError {
728  return "<span class='foswikiAlert'>".$_[0]."</span>";
729}
730
731###############################################################################
732sub writeDebug {
733  print STDERR "- FilterPlugin - $_[0]\n" if DEBUG;
734}
735
736
7371;
Note: See TracBrowser for help on using the repository browser.