← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 19:05:14 2015
Reported on Fri Jul 31 19:08:10 2015

Filename/var/www/foswiki11/lib/Foswiki/Plugins/FindElsewherePlugin/Core.pm
StatementsExecuted 58 statements in 1.85ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
51174µs7.55msFoswiki::Plugins::FindElsewherePlugin::Core::::_lazyInitFoswiki::Plugins::FindElsewherePlugin::Core::_lazyInit
51158µs7.63msFoswiki::Plugins::FindElsewherePlugin::Core::::handleFoswiki::Plugins::FindElsewherePlugin::Core::handle
51120µs20µsFoswiki::Plugins::FindElsewherePlugin::Core::::_debugFoswiki::Plugins::FindElsewherePlugin::Core::_debug
11116µs32µsFoswiki::Plugins::FindElsewherePlugin::Core::::BEGIN@23Foswiki::Plugins::FindElsewherePlugin::Core::BEGIN@23
11115µs20µsFoswiki::Plugins::FindElsewherePlugin::Core::::BEGIN@25Foswiki::Plugins::FindElsewherePlugin::Core::BEGIN@25
11113µs112µsFoswiki::Plugins::FindElsewherePlugin::Core::::BEGIN@33Foswiki::Plugins::FindElsewherePlugin::Core::BEGIN@33
0000s0sFoswiki::Plugins::FindElsewherePlugin::Core::::findTopicElsewhereFoswiki::Plugins::FindElsewherePlugin::Core::findTopicElsewhere
0000s0sFoswiki::Plugins::FindElsewherePlugin::Core::::makeSingularFoswiki::Plugins::FindElsewherePlugin::Core::makeSingular
0000s0sFoswiki::Plugins::FindElsewherePlugin::Core::::makeTopicLinkFoswiki::Plugins::FindElsewherePlugin::Core::makeTopicLink
0000s0sFoswiki::Plugins::FindElsewherePlugin::Core::::putBackBlocksFoswiki::Plugins::FindElsewherePlugin::Core::putBackBlocks
0000s0sFoswiki::Plugins::FindElsewherePlugin::Core::::takeOutBlocksFoswiki::Plugins::FindElsewherePlugin::Core::takeOutBlocks
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# Copyright (C) 2002 Mike Barton, Marco Carnut, Peter HErnst
2# (C) 2003 Martin Cleaver, (C) 2004 Matt Wilkie (C) 2007 Crawford Currie
3# (C) 2008 Foswiki Contributors
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#
18# This is the FindElsewhere Foswiki plugin,
19# see http://foswiki.org/Extensions/FindElsewherePlugin for details.
20
21package Foswiki::Plugins::FindElsewherePlugin::Core;
22
23266µs247µs
# spent 32µs (16+16) within Foswiki::Plugins::FindElsewherePlugin::Core::BEGIN@23 which was called: # once (16µs+16µs) by Foswiki::Plugins::FindElsewherePlugin::startRenderingHandler at line 23
use strict;
# spent 32µs making 1 call to Foswiki::Plugins::FindElsewherePlugin::Core::BEGIN@23 # spent 16µs making 1 call to strict::import
24
25
# spent 20µs (15+4) within Foswiki::Plugins::FindElsewherePlugin::Core::BEGIN@25 which was called: # once (15µs+4µs) by Foswiki::Plugins::FindElsewherePlugin::startRenderingHandler at line 31
BEGIN {
26 # Do a dynamic 'use locale' for this module
2714µs if( $Foswiki::useLocale || $Foswiki::cfg{UseLocale}) {
281600ns require locale;
2914µs14µs import locale ();
# spent 4µs making 1 call to locale::import
30 }
31146µs120µs}
32
3318µs199µs
# spent 112µs (13+99) within Foswiki::Plugins::FindElsewherePlugin::Core::BEGIN@33 which was called: # once (13µs+99µs) by Foswiki::Plugins::FindElsewherePlugin::startRenderingHandler at line 37
use vars qw(
# spent 99µs making 1 call to vars::import
34 $disabledFlag $disablePluralToSingular
35 $webNameRegex $wikiWordRegex $abbrevRegex $singleMixedAlphaNumRegex
36 $noAutolink $redirectable $initialised @webList %linkedWords $findAcronyms
3711.59ms1112µs );
38
391500ns$initialised = 0;
40
41516µs
# spent 20µs within Foswiki::Plugins::FindElsewherePlugin::Core::_debug which was called 5 times, avg 4µs/call: # 5 times (20µs+0s) by Foswiki::Plugins::FindElsewherePlugin::Core::handle at line 97, avg 4µs/call
sub _debug {
42 # Uncomment for debug
43 #Foswiki::Func::writeDebug( "FindElsewherePlugin: ".join(' ', @_));
44}
45
46
# spent 7.55ms (74µs+7.47) within Foswiki::Plugins::FindElsewherePlugin::Core::_lazyInit which was called 5 times, avg 1.51ms/call: # 5 times (74µs+7.47ms) by Foswiki::Plugins::FindElsewherePlugin::Core::handle at line 94, avg 1.51ms/call
sub _lazyInit {
47520µs return 1 if $initialised;
481200ns $initialised = 1;
49
5014µs141µs my $otherWebs = Foswiki::Func::getPreferencesValue( "LOOKELSEWHEREWEBS" );
# spent 41µs making 1 call to Foswiki::Func::getPreferencesValue
5113µs17.26ms unless( defined( $otherWebs)) {
# spent 7.26ms making 1 call to Foswiki::Func::getPluginPreferencesValue
52 # Compatibility, deprecated
53 $otherWebs = Foswiki::Func::getPluginPreferencesValue( "LOOKELSEWHEREWEBS" );
54 }
55
561500ns unless( defined( $otherWebs )) {
57 # SMELL: Retained for compatibility, but would be much better
58 # off without this, as we could use the absence of webs to mean the
59 # plugin is disabled.
60 $otherWebs = "System,Main";
61 }
62
6312µs125µs $findAcronyms = Foswiki::Func::getPreferencesValue( "LOOKELSEWHEREFORACRONYMS" ) || "all";
# spent 25µs making 1 call to Foswiki::Func::getPreferencesValue
64
6512µs133µs $disablePluralToSingular =
# spent 33µs making 1 call to Foswiki::Func::getPreferencesFlag
66 Foswiki::Func::getPreferencesFlag( "DISABLEPLURALTOSINGULAR" );
671200ns unless( defined( $disablePluralToSingular)) {
68 # Compatibility, deprecated
69 $disablePluralToSingular =
70 Foswiki::Func::getPluginPreferencesFlag( "DISABLEPLURALTOSINGULAR" );
71 }
72
73 $redirectable =
7411µs128µs Foswiki::Func::getPreferencesFlag( "LOOKELSEWHEREFORLOCAL" );
# spent 28µs making 1 call to Foswiki::Func::getPreferencesFlag
75
7614µs @webList = split( /[,\s]+/, $otherWebs );
77
7814µs16µs $webNameRegex = Foswiki::Func::getRegularExpression('webNameRegex');
# spent 6µs making 1 call to Foswiki::Func::getRegularExpression
7911µs12µs $wikiWordRegex = Foswiki::Func::getRegularExpression('wikiWordRegex');
# spent 2µs making 1 call to Foswiki::Func::getRegularExpression
801900ns12µs $abbrevRegex = Foswiki::Func::getRegularExpression('abbrevRegex');
# spent 2µs making 1 call to Foswiki::Func::getRegularExpression
81
8211µs172µs $noAutolink = Foswiki::Func::getPreferencesFlag('NOAUTOLINK');
# spent 72µs making 1 call to Foswiki::Func::getPreferencesFlag
83
8412µs12µs my $upperAlphaRegex = Foswiki::Func::getRegularExpression('upperAlpha');
# spent 2µs making 1 call to Foswiki::Func::getRegularExpression
8511µs11µs my $lowerAlphaRegex = Foswiki::Func::getRegularExpression('lowerAlpha');
# spent 1µs making 1 call to Foswiki::Func::getRegularExpression
861900ns12µs my $numericRegex = Foswiki::Func::getRegularExpression('numeric');
# spent 2µs making 1 call to Foswiki::Func::getRegularExpression
87113µs $singleMixedAlphaNumRegex = qr/[$upperAlphaRegex$lowerAlphaRegex$numericRegex]/;
88
89 # Plugin correctly initialized
9015µs return 1;
91}
92
93
# spent 7.63ms (58µs+7.57) within Foswiki::Plugins::FindElsewherePlugin::Core::handle which was called 5 times, avg 1.53ms/call: # 5 times (58µs+7.57ms) by Foswiki::Plugins::FindElsewherePlugin::startRenderingHandler at line 59 of /var/www/foswiki11/lib/Foswiki/Plugins/FindElsewherePlugin.pm, avg 1.53ms/call
sub handle {
94511µs57.55ms return unless _lazyInit();
# spent 7.55ms making 5 calls to Foswiki::Plugins::FindElsewherePlugin::Core::_lazyInit, avg 1.51ms/call
95
9652µs if ( $noAutolink ) {
97520µs520µs _debug('NOAUTOLINK set');
# spent 20µs making 5 calls to Foswiki::Plugins::FindElsewherePlugin::Core::_debug, avg 4µs/call
98516µs return;
99 }
100
101 unless (scalar(@webList)) {
102 _debug('no webs');
103 # no point if there are no webs to search
104 return;
105 }
106
107 # Find instances of WikiWords not in this web, but in the otherWeb(s)
108 # If the WikiWord is found in theWeb, put the word back unchanged
109 # If the WikiWord is found in the otherWeb, link to it via [[otherWeb.WikiWord]]
110 # If it isn't found there either, put the word back unchnaged
111
112 my $removed = {};
113 my $text = takeOutBlocks( $_[0], 'noautolink', $removed );
114
115 # Match
116 # 0) (Allowed preambles: "\s" and "(")
117 # 1) [[something]] - (including [[something][something]], but non-greedy),
118 # 2) WikiWordAsWebName.WikiWord,
119 # 3) WikiWords, and
120 # 4) WIK IWO RDS
121 %linkedWords = ();
122 $text =~ s/(\[\[.*?\]\]|(?:^|(?<=[\s\(,]))(?:$webNameRegex\.)?(?:$wikiWordRegex|$abbrevRegex))/findTopicElsewhere($_[1],$1)/geo;
123
124 putBackBlocks( \$text, $removed, 'noautolink' );
125
126 $_[0] = $text;
127}
128
129sub makeTopicLink {
130 ##my($otherWeb, $theTopic) = @_;
131 return "[[$_[0].$_[1]][$_[0]]]";
132}
133
134sub findTopicElsewhere {
135 # This was copied and pruned from Foswiki::internalLink
136 my( $theWeb, $theTopic ) = @_;
137 my $original = $theTopic;
138 my $linkText = $theTopic;
139 my $nonForcedAcronym = 0;
140
141 if ($theTopic =~ /^\[\[($webNameRegex)\.($wikiWordRegex)\](?:\[(.*)\])?\]$/o) {
142 if ($redirectable && $1 eq $theWeb) {
143 # The topic is *supposed* to be in this web, but the web is
144 # redirectable so we can ignore the web specifier
145 # remove the web name and continue
146 $theTopic = $2;
147 $linkText = $3 || $theTopic;
148 } else {
149 # The topic is an explicit link to another web
150 return $theTopic;
151 }
152 } elsif ($theTopic =~ /^\[\[($wikiWordRegex)\](?:\[(.*)\])?\]$/o) {
153 # No web specifier, look elsewhere
154 $theTopic = $1;
155 $linkText = $2 || $theTopic;
156 } elsif ($theTopic =~ /^\[\[($abbrevRegex)\](?:\[(.*)\])?\]$/o) {
157 # No web specifier, look elsewhere
158 $theTopic = $1;
159 $linkText = $2 || $theTopic;
160 } elsif ($theTopic =~ /^$abbrevRegex$/o) {
161 $nonForcedAcronym = 1;
162 } elsif ($theTopic =~ /^($webNameRegex)\.($wikiWordRegex)$/o) {
163 if ($redirectable && $1 eq $theWeb) {
164 $linkText = $theTopic = $2;
165 } else {
166 return $theTopic;
167 }
168 }
169
170 if ( $nonForcedAcronym ) {
171 return $theTopic if $findAcronyms eq "none";
172 return $linkedWords{$theTopic} if ( $findAcronyms eq "all" && $linkedWords{$theTopic} );
173 return $theTopic if ( $findAcronyms eq "first" && $linkedWords{$theTopic} );
174 }
175
176 # Turn spaced-out names into WikiWords - upper case first letter of
177 # whole link, and first of each word.
178 $theTopic =~ s/^(.)/\U$1/o;
179 $theTopic =~ s/\s($singleMixedAlphaNumRegex)/\U$1/go;
180 $theTopic =~ s/\[\[($singleMixedAlphaNumRegex)(.*)\]\]/\u$1$2/o;
181
182 # Look in the current web, return if found
183 my $exist = Foswiki::Func::topicExists( $theWeb, $theTopic );
184
185 if( ! $exist ) {
186 if( !$disablePluralToSingular && $theTopic =~ /s$/ ) {
187 my $theTopicSingular = makeSingular( $theTopic );
188 if( Foswiki::Func::topicExists( $theWeb, $theTopicSingular ) ) {
189 _debug("$theTopicSingular was found in $theWeb" );
190 return $original; # leave it as we found it
191 }
192 }
193 } else {
194 _debug("$theTopic was found in $theWeb: $linkText" );
195 return $original; # leave it as we found it
196 }
197
198 # Look in the other webs, return when found
199 my @topicLinks;
200
201 foreach ( @webList ) {
202 my $otherWeb = $_;
203
204 # For systems running WebNameAsWikiName
205 # If the $theTopic is a reference to a the name of
206 # otherWeb, point at otherWeb.WebHome - MRJC
207 if ($otherWeb eq $theTopic) {
208 _debug("$theTopic is the name of another web $otherWeb.");
209 return "[[$otherWeb.WebHome][$otherWeb]]";
210 }
211
212 my $exist = Foswiki::Func::topicExists( $otherWeb, $theTopic );
213 if( ! $exist ) {
214 if( !$disablePluralToSingular && $theTopic =~ /s$/ ) {
215 my $theTopicSingular = makeSingular( $theTopic );
216 if( Foswiki::Func::topicExists( $otherWeb, $theTopicSingular ) ) {
217 _debug("$theTopicSingular was found in $otherWeb");
218 push(@topicLinks, makeTopicLink($otherWeb, $theTopic));
219 }
220 }
221 }
222 else {
223 _debug("$theTopic was found in $otherWeb");
224 push(@topicLinks, makeTopicLink($otherWeb,$theTopic));
225 }
226 }
227
228 if (scalar(@topicLinks) > 0) {
229 if (scalar(@topicLinks) == 1) {
230 # Topic found in one place
231 # If link text [[was in this form]], free it
232 $linkText =~ s/\[\[(.*)\]\]/$1/o;
233
234 # Link to topic
235 $topicLinks[0] =~ s/(\[\[.*?\]\[)(.*?)(\]\])/$1$linkText$3/o;
236 $linkedWords{$theTopic} = $topicLinks[0];
237 return $topicLinks[0];
238 } else {
239 # topic found in several places
240 # If link text [[was in this form]] <em> it
241 $linkText =~ s/\[\[(.*)\]\]/<em>$1<\/em>/go;
242
243 # If $linkText is a WikiWord, prepend with <nop>
244 # (prevent double links)
245 $linkText =~ s/($wikiWordRegex)/<nop\/>$1/go;
246 my $renderedLink = "$linkText<sup>(".join(",", @topicLinks ).")</sup>";
247 $linkedWords{$theTopic} = $renderedLink;
248 return $renderedLink;
249 }
250 }
251 return $original;
252}
253
254sub makeSingular {
255 my ($theWord) = @_;
256
257 $theWord =~ s/ies$/y/o; # plurals like policy / policies
258 $theWord =~ s/sses$/ss/o; # plurals like address / addresses
259 $theWord =~ s/([Xx])es$/$1/o; # plurals like box / boxes
260 $theWord =~ s/([A-Za-rt-z])s$/$1/o; # others, excluding ending ss like address(es)
261 return $theWord;
262}
263
2641300nsmy $placeholderMarker = 0;
265
266sub takeOutBlocks {
267 my( $intext, $tag, $map ) = @_;
268
269 return $intext unless( $intext =~ m/<$tag\b/i );
270
271 my $out = '';
272 my $depth = 0;
273 my $scoop;
274 my $tagParams;
275
276 foreach my $token ( split/(<\/?$tag[^>]*>)/i, $intext ) {
277 if ($token =~ /<$tag\b([^>]*)?>/i) {
278 $depth++;
279 if ($depth eq 1) {
280 $tagParams = $1;
281 next;
282 }
283 } elsif ($token =~ /<\/$tag>/i) {
284 if ($depth > 0) {
285 $depth--;
286 if ($depth eq 0) {
287 my $placeholder = $tag.$placeholderMarker;
288 $placeholderMarker++;
289 $map->{$placeholder}{text} = $scoop;
290 $map->{$placeholder}{params} = $tagParams;
291 $out .= '<!--'.$Foswiki::TranslationToken.$placeholder.
292 $Foswiki::TranslationToken.'-->';
293 $scoop = '';
294 next;
295 }
296 }
297 }
298 if ($depth > 0) {
299 $scoop .= $token;
300 } else {
301 $out .= $token;
302 }
303 }
304
305 # unmatched tags
306 if (defined($scoop) && ($scoop ne '')) {
307 my $placeholder = $tag.$placeholderMarker;
308 $placeholderMarker++;
309 $map->{$placeholder}{text} = $scoop;
310 $map->{$placeholder}{params} = $tagParams;
311 $out .= '<!--'.$Foswiki::TranslationToken.$placeholder.
312 $Foswiki::TranslationToken.'-->';
313 }
314
315 return $out;
316}
317
318sub putBackBlocks {
319 my( $text, $map, $tag, $newtag, $callback ) = @_;
320
321 $newtag = $tag if (!defined($newtag));
322
323 foreach my $placeholder ( keys %$map ) {
324 if( $placeholder =~ /^$tag\d+$/ ) {
325 my $params = $map->{$placeholder}{params} || '';
326 my $val = $map->{$placeholder}{text};
327 $val = &$callback( $val ) if ( defined( $callback ));
328 if ($newtag eq '') {
329 $$text =~ s(<!--$Foswiki::TranslationToken$placeholder$Foswiki::TranslationToken-->)($val);
330 } else {
331 $$text =~ s(<!--$Foswiki::TranslationToken$placeholder$Foswiki::TranslationToken-->)
332 (<$newtag$params>$val</$newtag>);
333 }
334 delete( $map->{$placeholder} );
335 }
336 }
337}
338
33914µs1;