← 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/Search.pm
StatementsExecuted 420290 statements in 391ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
4111372ms1.07sFoswiki::Search::::formatResultsFoswiki::Search::formatResults
263675448.1ms48.1msFoswiki::Search::::metacacheFoswiki::Search::metacache
88002113.9ms13.9msFoswiki::Search::::_collate_to_listFoswiki::Search::_collate_to_list
41228.12ms49.8sFoswiki::Search::::searchWebFoswiki::Search::searchWeb
85117.71ms9.65msFoswiki::Search::::formatResultFoswiki::Search::formatResult
1112.55ms3.09msFoswiki::Search::::BEGIN@19Foswiki::Search::BEGIN@19
41112.33ms70.5msFoswiki::Search::::loadTemplatesFoswiki::Search::loadTemplates
170311.24ms1.65msFoswiki::Search::::__ANON__[:1336]Foswiki::Search::__ANON__[:1336]
41111.23ms13.5msFoswiki::Search::::parseSearchFoswiki::Search::parseSearch
111886µs1.06msFoswiki::Search::::BEGIN@24Foswiki::Search::BEGIN@24
111740µs818µsFoswiki::Search::::BEGIN@20Foswiki::Search::BEGIN@20
8221526µs526µsFoswiki::Search::::setup_callbackFoswiki::Search::setup_callback
111343µs456µsFoswiki::Search::::BEGIN@23Foswiki::Search::BEGIN@23
4111293µs293µsFoswiki::Search::::formatCommonFoswiki::Search::formatCommon
4111203µs10.6msFoswiki::Search::::__ANON__[:133]Foswiki::Search::__ANON__[:133]
8511143µs143µsFoswiki::Search::::__ANON__[:1014]Foswiki::Search::__ANON__[:1014]
851193µs93µsFoswiki::Search::::__ANON__[:1015]Foswiki::Search::__ANON__[:1015]
851192µs92µsFoswiki::Search::::__ANON__[:1018]Foswiki::Search::__ANON__[:1018]
851188µs88µsFoswiki::Search::::__ANON__[:1016]Foswiki::Search::__ANON__[:1016]
851188µs88µsFoswiki::Search::::__ANON__[:1017]Foswiki::Search::__ANON__[:1017]
851188µs88µsFoswiki::Search::::__ANON__[:1019]Foswiki::Search::__ANON__[:1019]
11182µs2.87msFoswiki::Search::::finishFoswiki::Search::finish
851179µs79µsFoswiki::Search::::__ANON__[:1020]Foswiki::Search::__ANON__[:1020]
851171µs71µsFoswiki::Search::::__ANON__[:1021]Foswiki::Search::__ANON__[:1021]
11114µs26µsFoswiki::Search::::BEGIN@12Foswiki::Search::BEGIN@12
11112µs17µsFoswiki::Search::::BEGIN@13Foswiki::Search::BEGIN@13
11111µs16µsFoswiki::Search::::BEGIN@26Foswiki::Search::BEGIN@26
11110µs10µsFoswiki::Search::::newFoswiki::Search::new
11110µs25µsFoswiki::Search::::BEGIN@14Foswiki::Search::BEGIN@14
1118µs117µsFoswiki::Search::::BEGIN@15Foswiki::Search::BEGIN@15
1115µs5µsFoswiki::Search::::BEGIN@21Foswiki::Search::BEGIN@21
1114µs4µsFoswiki::Search::::BEGIN@17Foswiki::Search::BEGIN@17
1114µs4µsFoswiki::Search::::BEGIN@18Foswiki::Search::BEGIN@18
1113µs3µsFoswiki::Search::::BEGIN@22Foswiki::Search::BEGIN@22
0000s0sFoswiki::Search::::__ANON__[:1003]Foswiki::Search::__ANON__[:1003]
0000s0sFoswiki::Search::::__ANON__[:1007]Foswiki::Search::__ANON__[:1007]
0000s0sFoswiki::Search::::__ANON__[:1011]Foswiki::Search::__ANON__[:1011]
0000s0sFoswiki::Search::::__ANON__[:138]Foswiki::Search::__ANON__[:138]
0000s0sFoswiki::Search::::__ANON__[:174]Foswiki::Search::__ANON__[:174]
0000s0sFoswiki::Search::::__ANON__[:177]Foswiki::Search::__ANON__[:177]
0000s0sFoswiki::Search::::__ANON__[:692]Foswiki::Search::__ANON__[:692]
0000s0sFoswiki::Search::::__ANON__[:693]Foswiki::Search::__ANON__[:693]
0000s0sFoswiki::Search::::__ANON__[:694]Foswiki::Search::__ANON__[:694]
0000s0sFoswiki::Search::::__ANON__[:695]Foswiki::Search::__ANON__[:695]
0000s0sFoswiki::Search::::__ANON__[:696]Foswiki::Search::__ANON__[:696]
0000s0sFoswiki::Search::::__ANON__[:697]Foswiki::Search::__ANON__[:697]
0000s0sFoswiki::Search::::__ANON__[:698]Foswiki::Search::__ANON__[:698]
0000s0sFoswiki::Search::::__ANON__[:699]Foswiki::Search::__ANON__[:699]
0000s0sFoswiki::Search::::__ANON__[:705]Foswiki::Search::__ANON__[:705]
0000s0sFoswiki::Search::::__ANON__[:709]Foswiki::Search::__ANON__[:709]
0000s0sFoswiki::Search::::__ANON__[:718]Foswiki::Search::__ANON__[:718]
0000s0sFoswiki::Search::::__ANON__[:984]Foswiki::Search::__ANON__[:984]
0000s0sFoswiki::Search::::__ANON__[:985]Foswiki::Search::__ANON__[:985]
0000s0sFoswiki::Search::::__ANON__[:986]Foswiki::Search::__ANON__[:986]
0000s0sFoswiki::Search::::__ANON__[:987]Foswiki::Search::__ANON__[:987]
0000s0sFoswiki::Search::::__ANON__[:999]Foswiki::Search::__ANON__[:999]
0000s0sFoswiki::Search::::_countPatternFoswiki::Search::_countPattern
0000s0sFoswiki::Search::::_extractPatternFoswiki::Search::_extractPattern
0000s0sFoswiki::Search::::_isSetTrueFoswiki::Search::_isSetTrue
0000s0sFoswiki::Search::::displayFormFieldFoswiki::Search::displayFormField
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# See bottom of file for license and copyright information
2package Foswiki::Search;
3
4=begin TML
5
6---+ package Foswiki::Search
7
8This module implements all the search functionality.
9
10=cut
11
12227µs238µs
# spent 26µs (14+12) within Foswiki::Search::BEGIN@12 which was called: # once (14µs+12µs) by Foswiki::search at line 12
use strict;
# spent 26µs making 1 call to Foswiki::Search::BEGIN@12 # spent 12µs making 1 call to strict::import
13226µs222µs
# spent 17µs (12+5) within Foswiki::Search::BEGIN@13 which was called: # once (12µs+5µs) by Foswiki::search at line 13
use warnings;
# spent 17µs making 1 call to Foswiki::Search::BEGIN@13 # spent 5µs making 1 call to warnings::import
14226µs241µs
# spent 25µs (10+15) within Foswiki::Search::BEGIN@14 which was called: # once (10µs+15µs) by Foswiki::search at line 14
use Assert;
# spent 25µs making 1 call to Foswiki::Search::BEGIN@14 # spent 16µs making 1 call to Assert::import
15228µs2227µs
# spent 117µs (8+109) within Foswiki::Search::BEGIN@15 which was called: # once (8µs+109µs) by Foswiki::search at line 15
use Error qw( :try );
# spent 117µs making 1 call to Foswiki::Search::BEGIN@15 # spent 109µs making 1 call to Error::import
16
17218µs14µs
# spent 4µs within Foswiki::Search::BEGIN@17 which was called: # once (4µs+0s) by Foswiki::search at line 17
use Foswiki ();
# spent 4µs making 1 call to Foswiki::Search::BEGIN@17
18217µs14µs
# spent 4µs within Foswiki::Search::BEGIN@18 which was called: # once (4µs+0s) by Foswiki::search at line 18
use Foswiki::Sandbox ();
# spent 4µs making 1 call to Foswiki::Search::BEGIN@18
19298µs13.09ms
# spent 3.09ms (2.55+543µs) within Foswiki::Search::BEGIN@19 which was called: # once (2.55ms+543µs) by Foswiki::search at line 19
use Foswiki::Search::InfoCache ();
# spent 3.09ms making 1 call to Foswiki::Search::BEGIN@19
202104µs1818µs
# spent 818µs (740+78) within Foswiki::Search::BEGIN@20 which was called: # once (740µs+78µs) by Foswiki::search at line 20
use Foswiki::Search::ResultSet ();
# spent 818µs making 1 call to Foswiki::Search::BEGIN@20
21218µs15µs
# spent 5µs within Foswiki::Search::BEGIN@21 which was called: # once (5µs+0s) by Foswiki::search at line 21
use Foswiki::ListIterator ();
# spent 5µs making 1 call to Foswiki::Search::BEGIN@21
22218µs13µs
# spent 3µs within Foswiki::Search::BEGIN@22 which was called: # once (3µs+0s) by Foswiki::search at line 22
use Foswiki::Iterator::FilterIterator ();
# spent 3µs making 1 call to Foswiki::Search::BEGIN@22
23289µs1456µs
# spent 456µs (343+113) within Foswiki::Search::BEGIN@23 which was called: # once (343µs+113µs) by Foswiki::search at line 23
use Foswiki::WebFilter ();
# spent 456µs making 1 call to Foswiki::Search::BEGIN@23
242116µs11.06ms
# spent 1.06ms (886µs+171µs) within Foswiki::Search::BEGIN@24 which was called: # once (886µs+171µs) by Foswiki::search at line 24
use Foswiki::MetaCache ();
# spent 1.06ms making 1 call to Foswiki::Search::BEGIN@24
25
26
# spent 16µs (11+5) within Foswiki::Search::BEGIN@26 which was called: # once (11µs+5µs) by Foswiki::search at line 35
BEGIN {
27
28 # 'Use locale' for internationalisation of Perl sorting and searching -
29 # main locale settings are done in Foswiki::setupLocale
30 # Do a dynamic 'use locale' for this module
3113µs if ( $Foswiki::cfg{UseLocale} ) {
321500ns require locale;
3313µs15µs import locale();
# spent 5µs making 1 call to locale::import
34 }
3514.92ms116µs}
# spent 16µs making 1 call to Foswiki::Search::BEGIN@26
36
37=begin TML
38
39---++ ClassMethod new ($session)
40
41Constructor for the singleton Search engine object.
42
43=cut
44
45
# spent 10µs within Foswiki::Search::new which was called: # once (10µs+0s) by Foswiki::search at line 2099 of /var/www/foswiki11/lib/Foswiki.pm
sub new {
4611µs my ( $class, $session ) = @_;
4717µs my $this = bless( { session => $session }, $class );
48
4916µs return $this;
50}
51
52=begin TML
53
54---++ ObjectMethod finish()
55Break circular references.
56
57 Note to developers; please undef *all* fields in the object explicitly,
58 whether they are references or not. That way this method is "golden
59 documentation" of the live fields in the object.
60
61=cut
62
63
# spent 2.87ms (82µs+2.79) within Foswiki::Search::finish which was called: # once (82µs+2.79ms) by Foswiki::finish at line 2163 of /var/www/foswiki11/lib/Foswiki.pm
sub finish {
641700ns my $this = shift;
6511µs undef $this->{session};
66
67# these may well be function objects, but if (a setting changes, it needs to be picked up again.
68153µs if ( defined( $this->{queryParser} ) ) {
6918µs12µs $this->{queryParser}->finish();
# spent 2µs making 1 call to Foswiki::Infix::Parser::finish
7011µs undef $this->{queryParser};
71 }
721600ns if ( defined( $this->{searchParser} ) ) {
73 $this->{searchParser}->finish();
74 undef $this->{searchParser};
75 }
7615µs if ( defined( $this->{MetaCache} ) ) {
7715µs12.79ms $this->{MetaCache}->finish();
# spent 2.79ms making 1 call to Foswiki::MetaCache::finish
781900ns undef $this->{MetaCache};
79 }
80}
81
82=begin TML
83
84---++ ObjectMethod metacache
85returns the metacache.
86
87=cut
88
89
# spent 48.1ms (48.1+33µs) within Foswiki::Search::metacache which was called 26367 times, avg 2µs/call: # 8845 times (13.4ms+0s) by Foswiki::Search::formatResults at line 787, avg 2µs/call # 8760 times (17.6ms+0s) by Foswiki::Search::InfoCache::addTopic at line 99 of /var/www/foswiki11/lib/Foswiki/Search/InfoCache.pm, avg 2µs/call # 8760 times (17.1ms+33µs) by Foswiki::Store::QueryAlgorithms::BruteForce::_webQuery at line 230 of /var/www/foswiki11/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm, avg 2µs/call # once (8µs+0s) by Foswiki::Users::TopicUserMapping::_getListOfGroups at line 1630 of /var/www/foswiki11/lib/Foswiki/Users/TopicUserMapping.pm # once (4µs+0s) by Foswiki::Store::QueryAlgorithms::BruteForce::_webQuery at line 114 of /var/www/foswiki11/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm
sub metacache {
90263678.88ms my $this = shift;
91
92# these may well be function objects, but if (a setting changes, it needs to be picked up again.
932636710.0ms133µs if ( !defined( $this->{MetaCache} ) ) {
# spent 33µs making 1 call to Foswiki::MetaCache::new
94 $this->{MetaCache} = new Foswiki::MetaCache( $this->{session} );
95 }
962636798.4ms return $this->{MetaCache};
97}
98
99=begin TML
100
101---++ ObjectMethod parseSearch($searchString, $params) -> Foswiki::*::Node
102
103parses the search string and builds the appropriate nodes (uses $param->{type} to work out which parser
104
105TODO: make parser register themselves with their type, so that we could plug in anything.
106
107=cut
108
109
# spent 13.5ms (1.23+12.3) within Foswiki::Search::parseSearch which was called 41 times, avg 329µs/call: # 41 times (1.23ms+12.3ms) by Foswiki::Search::searchWeb at line 351, avg 329µs/call
sub parseSearch {
1104119µs my $this = shift;
1114118µs my $searchString = shift;
1124112µs my $params = shift;
113
114418µs my $query;
115417µs my $theParser;
1164136µs if ( $params->{type} eq 'query' ) {
1174125µs unless ( defined( $this->{queryParser} ) ) {
1181500ns require Foswiki::Query::Parser;
11915µs11.01ms $this->{queryParser} = new Foswiki::Query::Parser();
# spent 1.01ms making 1 call to Foswiki::Query::Parser::new
120 }
1214125µs $theParser = $this->{queryParser};
122 }
123 else {
124 unless ( defined( $this->{searchParser} ) ) {
125 require Foswiki::Search::Parser;
126 $this->{searchParser} =
127 new Foswiki::Search::Parser( $this->{session} );
128 }
129 $theParser = $this->{searchParser};
130 }
131
# spent 10.6ms (203µs+10.4) within Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:133] which was called 41 times, avg 258µs/call: # 41 times (203µs+10.4ms) by Error::subs::try at line 419 of Error.pm, avg 258µs/call
try {
13241296µs4110.4ms $query = $theParser->parse( $searchString, $params );
# spent 10.4ms making 41 calls to Foswiki::Infix::Parser::parse, avg 253µs/call
133 }
134 catch Foswiki::Infix::Error with {
135
136 # Pass the error on to the caller
137 throw Error::Simple( shift->stringify() );
13841838µs123218µs };
# spent 161µs making 41 calls to Error::catch, avg 4µs/call # spent 57µs making 41 calls to Error::subs::with, avg 1µs/call # spent 11.0ms making 41 calls to Error::subs::try, avg 269µs/call, recursion: max depth 3, sum of overlapping time 11.0ms
13941107µs return $query;
140}
141
142sub _extractPattern {
143 my ( $text, $pattern ) = @_;
144
145 # Pattern comes from topic, therefore tainted
146 $pattern =
147 Foswiki::Sandbox::untaint( $pattern, \&Foswiki::validatePattern );
148
149 my $ok = 0;
150 eval {
151
152 # The eval acts as a try block in case there is anything evil in
153 # the pattern.
154 $ok = 1 if ( $text =~ s/$pattern/$1/is );
155 };
156 $text = '' unless $ok;
157
158 return $text;
159}
160
161# With the same argument as $pattern, returns a number which is the count of
162# occurences of the pattern argument.
163sub _countPattern {
164 my ( $text, $pattern ) = @_;
165
166 $pattern =
167 Foswiki::Sandbox::untaint( $pattern, \&Foswiki::validatePattern );
168
169 my $count;
170 try {
171
172 # see: perldoc -q count
173 $count = () = $text =~ /$pattern/g;
174 }
175 catch Error::Simple with {
176 $count = 0;
177 };
178
179 return $count;
180}
181
182=begin TML
183
184---++ StaticMethod _isSetTrue( $value, $default ) -> $boolean
185
186Returns 1 if =$value= is _actually set to_ true, and 0 otherwise.
187
188If the value is undef, then =$default= is returned. If =$default= is
189not specified it is taken as 0.
190
191=cut
192
193sub _isSetTrue {
194 my ( $value, $default ) = @_;
195
196 $default ||= 0;
197
198 return $default unless defined($value);
199
200 $value =~ s/on//gi;
201 $value =~ s/yes//gi;
202 $value =~ s/true//gi;
203 return ($value) ? 0 : 1;
204}
205
206=begin TML
207
208---++ ObjectMethod searchWeb (...)
209
210Search one or more webs according to the parameters.
211
212If =_callback= is set, that means the caller wants results as
213soon as they are ready. =_callback_ should be set to a reference
214to a function which takes =_cbdata= as the first parameter and
215remaining parameters the same as 'print'.
216
217If =_callback= is set, the result is always undef. Otherwise the
218result is a string containing the rendered search results.
219
220The function will throw Error::Simple if it encounters any problems with the
221syntax of the search string.
222
223Note: If =format= is set, =template= will be ignored.
224
225Note: For legacy, if =regex= is defined, it will force type='regex'
226
227If =type="word"= it will be changed to =type="keyword"= with =wordboundaries=1=. This will be used for searching with scope="text" only, because scope="topic" will do a Perl search on topic names.
228
229SMELL: If =template= is defined =bookview= will not work
230
231SMELL: it seems that if you define =_callback= then you are
232 responsible for converting the TML to HTML yourself!
233
234FIXME: =callback= cannot work with format parameter (consider format='| $topic |'
235
236=cut
237
238
# spent 49.8s (8.12ms+49.8) within Foswiki::Search::searchWeb which was called 41 times, avg 1.22s/call: # 40 times (7.89ms+49.6s) by Foswiki::__ANON__[/var/www/foswiki11/lib/Foswiki/Macros/SEARCH.pm:33] at line 32 of /var/www/foswiki11/lib/Foswiki/Macros/SEARCH.pm, avg 1.24s/call # once (235µs+218ms) by Foswiki::Users::TopicUserMapping::_getListOfGroups at line 1636 of /var/www/foswiki11/lib/Foswiki/Users/TopicUserMapping.pm
sub searchWeb {
2394120µs my $this = shift;
2404129µs my $session = $this->{session};
2414151µs4136µs ASSERT( defined $session->{webName} ) if DEBUG;
# spent 36µs making 41 calls to Assert::ASSERTS_OFF, avg 888ns/call
24241157µs my %params = @_;
243
24441185µs41708µs my $baseWebObject = Foswiki::Meta->new( $session, $session->{webName} );
# spent 708µs making 41 calls to Foswiki::Meta::new, avg 17µs/call
245
2464190µs41178µs my ( $callback, $cbdata ) = setup_callback( \%params, $baseWebObject );
# spent 178µs making 41 calls to Foswiki::Search::setup_callback, avg 4µs/call
247
2484133µs my $baseTopic = $params{basetopic} || $session->{topicName};
2494118µs my $baseWeb = $params{baseweb} || $session->{webName};
25041129µs4192µs $params{casesensitive} = Foswiki::isTrue( $params{casesensitive} );
# spent 92µs making 41 calls to Foswiki::isTrue, avg 2µs/call
2514148µs $params{excludeTopics} = $params{excludetopic} || '';
2524147µs my $formatDefined = $params{formatdefined} = defined $params{format};
2534117µs my $format = $params{format};
254
25541116µs4162µs $params{multiple} = Foswiki::isTrue( $params{multiple} );
# spent 62µs making 41 calls to Foswiki::isTrue, avg 2µs/call
256
257 # Let the search know we're only concerned with one hit per file
2584195µs41305µs $params{files_without_match} = not Foswiki::isTrue( $params{multiple} );
# spent 305µs making 41 calls to Foswiki::isTrue, avg 7µs/call
259
2604187µs41219µs $params{nonoise} = Foswiki::isTrue( $params{nonoise} );
# spent 219µs making 41 calls to Foswiki::isTrue, avg 5µs/call
26141117µs4177µs $params{noempty} = Foswiki::isTrue( $params{noempty}, $params{nonoise} );
# spent 77µs making 41 calls to Foswiki::isTrue, avg 2µs/call
262### $params{zeroresults} = Foswiki::isTrue( ( $params{zeroresults} ), $params{nonoise} );
263
264#paging - this code should be hidden in the InfoCache iterator, but atm, that won't let me do multi-web
265#TODO: or... I may wrap an AggregateIterator in a PagingIterator which then is evaluated by a Formattingiterator.
2664159µs my $pagesize =
267 $params{pagesize}
268 || $Foswiki::cfg{Search}{DefaultPageSize}
269 || 25;
270
2714131µs require Digest::MD5;
2724115µs my $string_id = $params{_RAW} || 'we had better not go there';
27341455µs41283µs my $paging_ID = 'SEARCH' . Digest::MD5::md5_hex($string_id);
# spent 283µs making 41 calls to Digest::MD5::md5_hex, avg 7µs/call
2744133µs $params{pager_urlparam_id} = $paging_ID;
275
276 # 1-based system; 0 is not a valid page number
27741242µs82861µs my $showpage =
# spent 781µs making 41 calls to Foswiki::Request::param, avg 19µs/call # spent 80µs making 41 calls to Foswiki::isTrue, avg 2µs/call
278 $session->{request}->param($paging_ID)
279 || $params{showpage}
280 || ( Foswiki::isTrue( $params{pager} ) ? 1 : undef );
281
2824131µs if ( defined( $params{pagesize} ) or defined($showpage) ) {
283 if ( !defined($showpage) ) {
284 $showpage = 1;
285 }
286 $params{pager_skip_results_from} = $pagesize * ( $showpage - 1 );
287 $params{pager_show_results_to} = $pagesize;
288 }
289
290 #TODO: refactorme
2914119µs my $header = $params{header};
2924145µs my $footer = $params{footer};
29341105µs4169µs my $noTotal = Foswiki::isTrue( $params{nototal}, $params{nonoise} );
# spent 69µs making 41 calls to Foswiki::isTrue, avg 2µs/call
294
2954169µs41238µs my $noEmpty = Foswiki::isTrue( $params{noempty}, $params{nonoise} );
# spent 238µs making 41 calls to Foswiki::isTrue, avg 6µs/call
296
297 # Note: a defined header/footer overrides noheader/nofooter
298 # To maintain Cairo compatibility we ommit default header/footer if the
29941125µs4168µs my $noHeader =
# spent 68µs making 41 calls to Foswiki::isTrue, avg 2µs/call
300 !defined($header)
301 && Foswiki::isTrue( $params{noheader}, $params{nonoise} )
302 || ( !$header && $formatDefined );
303
3044145µs12µs my $noFooter =
# spent 2µs making 1 call to Foswiki::isTrue
305 !defined($footer)
306 && Foswiki::isTrue( $params{nofooter}, $params{nonoise} )
307 || ( !$footer && $formatDefined );
308
3094179µs4161µs my $noSummary = Foswiki::isTrue( $params{nosummary}, $params{nonoise} );
# spent 61µs making 41 calls to Foswiki::isTrue, avg 1µs/call
3104177µs4154µs my $zeroResults =
# spent 54µs making 41 calls to Foswiki::isTrue, avg 1µs/call
311 Foswiki::isTrue( $params{zeroresults}, $params{nonoise} || 1 );
312
313 #END TODO
314
3154172µs4157µs my $doBookView = Foswiki::isTrue( $params{bookview} );
# spent 57µs making 41 calls to Foswiki::isTrue, avg 1µs/call
316
3174160µs4153µs my $revSort = Foswiki::isTrue( $params{reverse} );
# spent 53µs making 41 calls to Foswiki::isTrue, avg 1µs/call
3184141µs $params{scope} = $params{scope} || '';
3194130µs my $searchString = defined $params{search} ? $params{search} : '';
320
3214140µs $params{includeTopics} = $params{topic} || '';
3224117µs $params{type} = $params{type} || '';
323
3244140µs $params{wordboundaries} = 0;
3254126µs if ( $params{type} eq 'word' ) {
326
327 # 'word' is exactly the same as 'keyword', except we will be searching
328 # with word boundaries
329 $params{type} = 'keyword';
330 $params{wordboundaries} = 1;
331 }
332
3334160µs my $webNames = $params{web} || '';
3344140µs my $date = $params{date} || '';
3354142µs my $recurse = $params{'recurse'} || '';
336
3374170µs $baseWeb =~ s/\./\//go;
338
3394120µs $params{type} = 'regex' if ( $params{regex} );
340
341#TODO: quick hackjob - see what the feature proposal gives before it becomes public
3424132µs if ( defined( $params{groupby} ) and ( $params{groupby} eq 'none' ) ) {
343
344 #_only_ allow groupby="none" - as its a secrect none public setting.
345 }
346 else {
3474146µs $params{groupby} = 'web';
348 }
349
350################### Perform The Search
35141145µs4113.5ms my $query = $this->parseSearch( $searchString, \%params );
# spent 13.5ms making 41 calls to Foswiki::Search::parseSearch, avg 329µs/call
352
353#setting the inputTopicSet to be undef allows the search/query algo to use
354#the topic="" and excludetopic="" params and web Obj to get a new list of topics.
355#this allows the algo's to customise and optimise the getting of this list themselves.
35641158µs4148.7s my $infoCache = Foswiki::Meta::query( $query, undef, \%params );
# spent 48.7s making 41 calls to Foswiki::Meta::query, avg 1.19s/call
357
358################### Do the Rendering
359
360 # If the search did not return anything, return the rendered zeroresults
361 # if it is defined as a string.
362 # (http://foswiki.org/Development/AddDefaultTopicParameterToINCLUDE)
36341102µs41879µs if ( not $infoCache->hasNext() ) {
# spent 879µs making 41 calls to Foswiki::Search::ResultSet::hasNext, avg 21µs/call
364 if ( not $zeroResults ) {
365 return '';
366 }
367 else {
368 if ( not _isSetTrue( $params{zeroresults}, 1 ) ) {
369
370#foswiki 1.1 Feature Proposal: SEARCH needs an alt parameter in case of zero results
371
372 #TODO: extract & merge with extraction of footer processing code below
373 my $result = $params{zeroresults};
374
375 $result =~ s/\$web/$baseWeb/gos; # expand name of web
376 $result =~ s/([^\n])$/$1\n/os; # add new line at end
377
378 # output footer of $web
379 $result =~ s/\$ntopics/0/gs;
380 $result =~ s/\$nhits/0/gs;
381 $result =~ s/\$index/0/gs;
382
383 #legacy SEARCH counter support
384 $result =~ s/%NTOPICS%/0/go;
385
386 $result = Foswiki::expandStandardEscapes($result);
387 $result =~ s/\n$//os; # remove trailing new line
388
389 return $result;
390 }
391 }
392 }
393
39441353µs4170.5ms my $tmplSearch =
# spent 70.5ms making 41 calls to Foswiki::Search::loadTemplates, avg 1.72ms/call
395 $this->loadTemplates( \%params, $baseWebObject, $formatDefined,
396 $doBookView, $noHeader, $noSummary, $noTotal, $noFooter );
397
398 # Generate 'Search:' part showing actual search string used
399 # Ommit any text before search results if either nosearch or nonoise is on
40041113µs41399µs my $nonoise = Foswiki::isTrue( $params{nonoise} );
# spent 399µs making 41 calls to Foswiki::isTrue, avg 10µs/call
40141102µs4180µs my $noSearch = Foswiki::isTrue( $params{nosearch}, $nonoise );
# spent 80µs making 41 calls to Foswiki::isTrue, avg 2µs/call
4024115µs unless ($noSearch) {
403 my $searchStr = $searchString;
404 $searchStr =~ s/&/&/go;
405 $searchStr =~ s/</&lt;/go;
406 $searchStr =~ s/>/&gt;/go;
407
408 $tmplSearch =~ s/%SEARCHSTRING%/$searchStr/go;
409 &$callback( $cbdata, $tmplSearch );
410 }
411
412 # We now format the results.
413 # All the
41441299µs411.07s my ( $numberOfResults, $web_searchResult ) =
# spent 1.07s making 41 calls to Foswiki::Search::formatResults, avg 26.0ms/call
415 $this->formatResults( $query, $infoCache, \%params );
416
417#worst possible way to do this: copy the entire if() statement from a few lines higher up
418#we need to repeat it in 1.1, as the paging is in formatResults, whereas in 1.2, search returns
419#a Paging Iterator.
420#Sven has decided as this is probably the final 1.1 patch release, that its going to be more
421#obvious not to extract to a function
4224117µs if ( $numberOfResults == 0 ) {
423 if ( not $zeroResults ) {
424 return '';
425 }
426 else {
427 if ( not _isSetTrue( $params{zeroresults}, 1 ) ) {
428
429#foswiki 1.1 Feature Proposal: SEARCH needs an alt parameter in case of zero results
430
431 #TODO: extract & merge with extraction of footer processing code below
432 my $result = $params{zeroresults};
433
434 $result =~ s/\$web/$baseWeb/gos; # expand name of web
435 $result =~ s/([^\n])$/$1\n/os; # add new line at end
436
437 # output footer of $web
438 $result =~ s/\$ntopics/0/gs;
439 $result =~ s/\$nhits/0/gs;
440 $result =~ s/\$index/0/gs;
441
442 #legacy SEARCH counter support
443 $result =~ s/%NTOPICS%/0/go;
444
445 $result = Foswiki::expandStandardEscapes($result);
446 $result =~ s/\n$//os; # remove trailing new line
447
448 return $result;
449 }
450 }
451 }
452
4534146µs return if ( defined $params{_callback} );
454
45540272µs my $searchResult = join( '', @{ $params{_cbdata} } );
456
45740196µs40508µs $searchResult = Foswiki::expandStandardEscapes($searchResult);
# spent 508µs making 40 calls to Foswiki::expandStandardEscapes, avg 13µs/call
458
459 # Remove trailing separator or new line if nofinalnewline parameter is set
46040129µs4090µs my $noFinalNewline = Foswiki::isTrue( $params{nofinalnewline}, 1 );
# spent 90µs making 40 calls to Foswiki::isTrue, avg 2µs/call
4614033µs if ( $formatDefined && $noFinalNewline ) {
4624022µs if ( $params{separator} ) {
463 my $separator = quotemeta( $params{separator} );
464 $searchResult =~ s/$separator$//s; # remove separator at end
465 }
466 else {
4674052µs $searchResult =~ s/\n$//os; # remove trailing new line
468 }
469 }
470
471401.98ms return $searchResult;
472}
473
474=begin TML
475
476---++ ObjectMethod loadTemplates (...)
477
478this code was extracted from searchWeb, and should probably be private.
479
480=cut
481
482
# spent 70.5ms (2.33+68.1) within Foswiki::Search::loadTemplates which was called 41 times, avg 1.72ms/call: # 41 times (2.33ms+68.1ms) by Foswiki::Search::searchWeb at line 394, avg 1.72ms/call
sub loadTemplates {
483 my (
48441118µs $this, $params, $baseWebObject,
485 $formatDefined, $doBookView, $noHeader,
486 $noSummary, $noTotal, $noFooter
487 ) = @_;
488
4894152µs my $session = $this->{session};
490
491 #tmpl loading code.
4924130µs my $tmpl = '';
493
4944144µs my $template = $params->{template} || '';
4954126µs if ($formatDefined) {
496 $template = 'searchformat';
497 }
498 elsif ($template) {
499
500 # template definition overrides book and rename views
501 }
502 elsif ($doBookView) {
503 $template = 'searchbookview';
504 }
505 else {
506 $template = 'search';
507 }
50841433µs8253.4ms $tmpl = $session->templates->readTemplate($template);
# spent 53.2ms making 41 calls to Foswiki::Templates::readTemplate, avg 1.30ms/call # spent 213µs making 41 calls to Foswiki::templates, avg 5µs/call
509
510#print STDERR "}}} $tmpl {{{\n";
511# SMELL: the only META tags in a template will be METASEARCH
512# Why the heck are they being filtered????
513#TODO: write a unit test that uses topic based templates with META's in them and if ok, remove.
5144145µs $tmpl =~ s/\%META{.*?}\%//go; # remove %META{'parent'}%
515
516 # Split template into 5 sections
5174167µs my ( $tmplHead, $tmplSearch, $tmplTable, $tmplNumber, $tmplTail ) =
518 split( /%SPLIT%/, $tmpl );
519
5204111µs my $repeatText;
521
5224134µs if ( !defined($tmplTail) ) {
52341252µs824.41ms $tmplSearch = $session->templates->expandTemplate('SEARCH:searched');
# spent 4.31ms making 41 calls to Foswiki::Templates::expandTemplate, avg 105µs/call # spent 104µs making 41 calls to Foswiki::templates, avg 3µs/call
52441131µs828.45ms $tmplNumber = $session->templates->expandTemplate('SEARCH:count');
# spent 8.37ms making 41 calls to Foswiki::Templates::expandTemplate, avg 204µs/call # spent 75µs making 41 calls to Foswiki::templates, avg 2µs/call
525
526#it'd be nice to not need this if, but it seem that the noheader setting is ignored if a header= is set. truely bizzare
527#TODO: push up the 'noheader' evaluation to take not of this quirk
528#TODO: um, we die when ASSERT is on with a wide char in print
5294123µs unless ($noHeader) {
530 $params->{header} =
531 $session->templates->expandTemplate('SEARCH:header')
532 unless defined $params->{header};
533 }
534
53541127µs821.82ms $repeatText = $session->templates->expandTemplate('SEARCH:format');
# spent 1.75ms making 41 calls to Foswiki::Templates::expandTemplate, avg 43µs/call # spent 73µs making 41 calls to Foswiki::templates, avg 2µs/call
536
5374175µs unless ($noFooter) {
538 $params->{footer} =
539 $session->templates->expandTemplate('SEARCH:footer')
540 unless defined $params->{footer};
541 }
542 }
543 else {
544
545 #Historical legacy form of the search TMPL's
546 # header and footer of $web
547 my $beforeText;
548 my $afterText;
549 ( $beforeText, $repeatText, $afterText ) =
550 split( /%REPEAT%/, $tmplTable );
551
552 unless ($noHeader) {
553 $params->{header} = $beforeText unless defined $params->{header};
554 }
555
556 unless ($noFooter) {
557 $params->{footer} ||= $afterText;
558 }
559 }
560
561 #nosummary="on" nosearch="on" noheader="on" nototal="on"
5624128µs if ($noSummary) {
5634125µs $repeatText =~ s/%TEXTHEAD%//go;
5644112µs $repeatText =~ s/&nbsp;//go;
565 }
566 else {
567 $repeatText =~ s/%TEXTHEAD%/\$summary(searchcontext)/go;
568 }
5694145µs $params->{format} ||= $repeatText;
570
5714192µs $params->{footercounter} ||= $tmplNumber;
572
57341145µs return $tmplSearch;
574}
575
576=begin TML
577---++ formatResults
578
579the implementation of %FORMAT{}%
580
581TODO: rewrite to take a resultset, a set of params? and a hash of sub's to
582enable evaluations of things like '$include(blah)' in format strings.
583
584have a default set of replacements like $lt, $nop, $percnt, $dollar etc, and then
585the hash of subs can take care of %MACRO{}% specific complex to evaluate replacements..
586
587(that way we don't pre-evaluate and then subst)
588
589=cut
590
591
# spent 1.07s (372ms+693ms) within Foswiki::Search::formatResults which was called 41 times, avg 26.0ms/call: # 41 times (372ms+693ms) by Foswiki::Search::searchWeb at line 414, avg 26.0ms/call
sub formatResults {
5924150µs my ( $this, $query, $infoCache, $params ) = @_;
5934127µs my $session = $this->{session};
5944156µs my $users = $session->{users};
595
59641180µs41348µs my ( $callback, $cbdata ) = setup_callback($params);
# spent 348µs making 41 calls to Foswiki::Search::setup_callback, avg 8µs/call
597
5984163µs my $baseTopic = $session->{topicName};
5994127µs my $baseWeb = $session->{webName};
6004179µs4166µs my $doBookView = Foswiki::isTrue( $params->{bookview} );
# spent 66µs making 41 calls to Foswiki::isTrue, avg 2µs/call
60141102µs41215µs my $caseSensitive = Foswiki::isTrue( $params->{casesensitive} );
# spent 215µs making 41 calls to Foswiki::isTrue, avg 5µs/call
60241105µs4172µs my $doExpandVars = Foswiki::isTrue( $params->{expandvariables} );
# spent 72µs making 41 calls to Foswiki::isTrue, avg 2µs/call
6034166µs41182µs my $nonoise = Foswiki::isTrue( $params->{nonoise} );
# spent 182µs making 41 calls to Foswiki::isTrue, avg 4µs/call
6044191µs4164µs my $noSearch = Foswiki::isTrue( $params->{nosearch}, $nonoise );
# spent 64µs making 41 calls to Foswiki::isTrue, avg 2µs/call
6054124µs my $formatDefined = defined $params->{format};
6064118µs my $format = $params->{format} || '';
6074125µs my $header = $params->{header} || '';
6084129µs my $footer = $params->{footer} || '';
6094124µs my $limit = $params->{limit} || '';
610
611 # Limit search results. Cannot be deprecated
612 # Limit will still be needed for the application types of SEARCHES
613 # even if pagesize is added as feature. Example for searching and listing
614 # text from first 5 bullets in a formatted multiple type search
6154136µs if ( $limit =~ /(^\d+$)/o ) {
616
617 # only digits, all else is the same as
618 # an empty string. "+10" won't work.
619 $limit = $1;
620 }
621 else {
622
623 # change 'all' to 0, then to big number
6244115µs $limit = 0;
625 }
6264116µs $limit = 32000 unless ($limit);
627
628 #pager formatting
6294112µs my %pager_formatting;
6304127µs if ( defined( $params->{pager_show_results_to} )
631 and $params->{pager_show_results_to} > 0 )
632 {
633 $limit = $params->{pager_show_results_to};
634
635#paging - this code should be hidden in the InfoCache iterator, but atm, that won't let me do multi-web
636 my $pagesize =
637 $params->{pagesize}
638 || $Foswiki::cfg{Search}{DefaultPageSize}
639 || 25;
640
641 #TODO: paging only implemented for SEARCH atm :/
642 my $paging_ID = $params->{pager_urlparam_id};
643
644 # 1-based system; 0 is not a valid page number
645 my $showpage =
646 $session->{request}->param($paging_ID)
647 || $params->{showpage}
648 || 1;
649
650 #TODO: need to ask the ResultSet
651 my $numberofpages = 0;
652 $numberofpages = ( $infoCache->numberOfTopics / $params->{pagesize} )
653 if $params->{pagesize};
654 $numberofpages = int($numberofpages) + 1;
655
656 #TODO: excuse me?
657 my $sep = ' ';
658
659 my $nextidx = $showpage + 1;
660 my $previousidx = $showpage - 1;
661
662 my %new_params;
663
664 #kill me please, i can't find a way to just load up the hash :(
665 foreach my $key ( $session->{request}->param ) {
666 $new_params{$key} = $session->{request}->param($key);
667 }
668
669 $session->templates->readTemplate('searchformat');
670
671 my $previouspagebutton = '';
672 my $previouspageurl = '';
673 if ( $previousidx >= 1 ) {
674 $new_params{$paging_ID} = $previousidx;
675 $previouspageurl =
676 Foswiki::Func::getScriptUrl( $baseWeb, $baseTopic, 'view',
677 %new_params );
678 $previouspagebutton =
679 $session->templates->expandTemplate('SEARCH:pager_previous');
680 }
681 my $nextpagebutton = '';
682 my $nextpageurl = '';
683 if ( $nextidx <= $numberofpages ) {
684 $new_params{$paging_ID} = $nextidx;
685 $nextpageurl =
686 Foswiki::Func::getScriptUrl( $baseWeb, $baseTopic, 'view',
687 %new_params );
688 $nextpagebutton =
689 $session->templates->expandTemplate('SEARCH:pager_next');
690 }
691 %pager_formatting = (
692 '\$previouspage' => sub { return $previousidx },
693 '\$currentpage' => sub { return $showpage },
694 '\$nextpage' => sub { return $showpage + 1 },
695 '\$numberofpages' => sub { return $numberofpages },
696 '\$pagesize' => sub { return $pagesize },
697 '\$previousurl' => sub { return $previouspageurl },
698 '\$nexturl' => sub { return $nextpageurl },
699 '\$sep' => sub { return $sep; }
700 );
701
702 $previouspagebutton =
703 $this->formatCommon( $previouspagebutton, \%pager_formatting );
704 $pager_formatting{'\$previousbutton'} =
705 sub { return $previouspagebutton };
706
707 $nextpagebutton =
708 $this->formatCommon( $nextpagebutton, \%pager_formatting );
709 $pager_formatting{'\$nextbutton'} = sub { return $nextpagebutton };
710
711 my $pager_control = '';
712 if ( $numberofpages > 1 ) {
713 $pager_control = $params->{pagerformat}
714 || $session->templates->expandTemplate('SEARCH:pager');
715 $pager_control =
716 $this->formatCommon( $pager_control, \%pager_formatting );
717 }
718 $pager_formatting{'\$pager'} = sub { return $pager_control; };
719 }
720
721 #TODO: multiple is an attribute of the ResultSet
72241114µs41194µs my $doMultiple = Foswiki::isTrue( $params->{multiple} );
# spent 194µs making 41 calls to Foswiki::isTrue, avg 5µs/call
7234188µs41182µs my $noEmpty = Foswiki::isTrue( $params->{noempty}, $nonoise );
# spent 182µs making 41 calls to Foswiki::isTrue, avg 4µs/call
724
725 # Note: a defined header/footer overrides noheader/nofooter
726 # To maintain Cairo compatibility we ommit default header/footer if the
7274165µs my $noHeader =
728 !defined($header) && Foswiki::isTrue( $params->{noheader}, $nonoise )
729 || ( !$header && $formatDefined );
730
7314131µs my $noFooter =
732 !defined($footer) && Foswiki::isTrue( $params->{nofooter}, $nonoise )
733 || ( !$footer && $formatDefined );
734
7354189µs4166µs my $noSummary = Foswiki::isTrue( $params->{nosummary}, $nonoise );
# spent 66µs making 41 calls to Foswiki::isTrue, avg 2µs/call
7364172µs4155µs my $zeroResults =
# spent 55µs making 41 calls to Foswiki::isTrue, avg 1µs/call
737 Foswiki::isTrue( ( $params->{zeroresults} ), $nonoise || 1 );
7384187µs4155µs my $noTotal = Foswiki::isTrue( $params->{nototal}, $nonoise );
# spent 55µs making 41 calls to Foswiki::isTrue, avg 1µs/call
7394136µs my $newLine = $params->{newline} || '';
7404118µs my $separator = $params->{separator};
7414130µs my $type = $params->{type} || '';
742
743 # output the list of topics in $web
7444110µs my $ntopics = 0; # number of topics in current web
745415µs my $nhits = 0; # number of hits (if multiple=on) in current web
7464112µs my $headerDone = $noHeader;
747
7484111µs my $web = $baseWeb;
74941372µs411.20ms my $webObject = new Foswiki::Meta( $session, $web );
# spent 1.20ms making 41 calls to Foswiki::Meta::new, avg 29µs/call
7504118µs my $lastWebProcessed = '';
751
752 #total number of topics and hits - not reset when we swap webs
753416µs my $ttopics = 0;
754419µs my $thits = 0;
755
7564188µs4165µs while ( $infoCache->hasNext() ) {
# spent 65µs making 41 calls to Foswiki::Search::ResultSet::hasNext, avg 2µs/call
757884514.3ms884551.6ms my $listItem = $infoCache->next();
# spent 51.6ms making 8845 calls to Foswiki::Search::ResultSet::next, avg 6µs/call
75888458.64ms88457.46ms ASSERT( defined($listItem) ) if DEBUG;
# spent 7.46ms making 8845 calls to Assert::ASSERTS_OFF, avg 843ns/call
759
760 #pager..
76188452.76ms if ( defined( $params->{pager_skip_results_from} )
762 and $params->{pager_skip_results_from} > 0 )
763 {
764 $params->{pager_skip_results_from}--;
765 next;
766 }
767
768 #############################################################
769 #TOPIC specific
77088453.33ms my $topic = $listItem;
7718845712µs my $text; #undef means the formatResult() gets it from $info->text;
7728845659µs my $info;
77388453.08ms my @multipleHitLines = ();
774884547.2ms88457.84ms if (
# spent 7.84ms making 8845 calls to UNIVERSAL::isa, avg 887ns/call
775 ( $infoCache->isa('Foswiki::Search::ResultSet') ) or #SEARCH
776 ( $infoCache->isa('Foswiki::Search::InfoCache') )
777 ) #FORMAT
778 {
779884515.3ms8845191ms ( $web, $topic ) =
# spent 191ms making 8845 calls to Foswiki::Func::normalizeWebTopicName, avg 22µs/call
780 Foswiki::Func::normalizeWebTopicName( '', $listItem );
781
782# add dependencies (TODO: unclear if this should be before the paging, or after the allowView - sadly, it can't be _in_ the infoCache)
78388454.78ms if ( my $cache = $session->{cache} ) {
784 $cache->addDependency( $web, $topic );
785 }
786
787884519.0ms17690170ms $info = $this->metacache->get( $web, $topic );
# spent 157ms making 8845 calls to Foswiki::MetaCache::get, avg 18µs/call # spent 13.4ms making 8845 calls to Foswiki::Search::metacache, avg 2µs/call
788
789# Check security (don't show topics the current user does not have permission to view)
79088453.67ms next unless $info->{allowView};
791
792 # Special handling for format='...'
79388452.33ms if ($formatDefined) {
794884512.3ms884545.5ms $text = $info->{tom}->text();
# spent 45.5ms making 8845 calls to Foswiki::Meta::text, avg 5µs/call
79588451.16ms $text = '' unless defined $text;
796
79788452.01ms if ($doExpandVars) {
798 if ( $web eq $baseWeb && $topic eq $baseTopic ) {
799
800 # primitive way to prevent recursion
801 $text =~ s/%SEARCH/%<nop>SEARCH/g;
802 }
803 $text = $info->{tom}->expandMacros($text);
804 }
805 }
806
807 #TODO: should extract this somehow
808
80988452.53ms if ( $doMultiple && $query->{tokens} ) {
810
811 #TODO: Sven wonders if this should be a HoistRE..
812 #TODO: well, um, and how does this work for query search?
813 my @tokens = @{ $query->{tokens} };
814 my $pattern = $tokens[$#tokens]; # last token in an AND search
815 $pattern = quotemeta($pattern) if ( $type ne 'regex' );
816 $text = $info->{tom}->text() unless defined $text;
817 $text = '' unless defined $text;
818
819 if ($caseSensitive) {
820 @multipleHitLines =
821 reverse grep { /$pattern/ } split( /[\n\r]+/, $text );
822 }
823 else {
824 @multipleHitLines =
825 reverse grep { /$pattern/i } split( /[\n\r]+/, $text );
826 }
827 }
828 }
829
83088452.35ms $ntopics += 1;
83188451.06ms $ttopics += 1;
83288455.33ms do { # multiple=on loop
833
83488451.17ms $nhits += 1;
8358845763µs $thits += 1;
836
83788452.22ms $text = pop(@multipleHitLines) if ( scalar(@multipleHitLines) );
838
83988451.62ms my $justdidHeaderOrFooter = 0;
84088456.48ms if ( ( defined( $params->{groupby} ) )
841 and ( $params->{groupby} eq 'web' ) )
842 {
84388451.87ms if ( $lastWebProcessed ne $web ) {
844
845 #output the footer for the previous listItem
8464115µs if ( $lastWebProcessed ne '' ) {
847
848 #c&p from below
849 #TODO: needs refactoring.
850 my $processedfooter = $footer;
851 if ( not $noTotal ) {
852 $processedfooter .= $params->{footercounter};
853 }
854 if ( defined($processedfooter)
855 and ( $processedfooter ne '' ) )
856 {
857
858 #footer comes before result
859 $ntopics--;
860 $nhits--;
861
862#because $pager contains more $ntopics like format strings, it needs to be expanded first.
863 $processedfooter =
864 $this->formatCommon( $processedfooter,
865 \%pager_formatting );
866 $processedfooter =~ s/\$web/$lastWebProcessed/gos
867 ; # expand name of web
868
869 # $processedfooter =~
870 # s/([^\n])$/$1\n/os; # add new line at end
871 # output footer of $web
872
873 $processedfooter =~ s/\$ntopics/$ntopics/gs;
874 $processedfooter =~ s/\$nhits/$nhits/gs;
875 $processedfooter =~ s/\$index/$thits/gs;
876
877 #legacy SEARCH counter support
878 $processedfooter =~ s/%NTOPICS%/$ntopics/go;
879
880 $processedfooter =
881 $this->formatCommon( $processedfooter,
882 \%pager_formatting );
883
884 # $processedfooter =~
885 # s/\n$//os; # remove trailing new line
886
887 $justdidHeaderOrFooter = 1;
888 &$callback( $cbdata, $processedfooter );
889
890 #go back to counting results
891 $ntopics++;
892 $nhits++;
893 }
894 }
895
896 #trigger a header for this new web
897419µs $headerDone = undef;
898 }
899 }
900
90188451.30ms if ( $lastWebProcessed ne $web ) {
90241177µs41627µs $webObject = new Foswiki::Meta( $session, $web );
# spent 627µs making 41 calls to Foswiki::Meta::new, avg 15µs/call
903418µs $lastWebProcessed = $web;
904
905 #reset our web partitioned legacy counts
9064114µs $ntopics = 1;
9074111µs $nhits = 1;
908 }
909
910 # lazy output of header (only if needed for the first time)
91188453.05ms if ( ( !$headerDone and ( defined($header) ) )
912 and ( $header ne '' ) )
913 {
914
915 my $processedheader = $header;
916
917 # because $pager contains more $ntopics like format
918 # strings, it needs to be expanded first.
919 $processedheader =
920 $this->formatCommon( $processedheader, \%pager_formatting );
921 $processedheader =~ s/\$web/$web/gos; # expand name of web
922
923 # add new line after the header unless separator is defined
924 # per Item1773 / SearchSeparatorDefaultHeaderFooter
925 unless ( defined $separator ) {
926 $processedheader =~ s/([^\n])$/$1\n/os;
927 }
928
929 $headerDone = 1;
930 my $thisWebBGColor = $webObject->getPreference('WEBBGCOLOR')
931 || '\#FF00FF';
932 $processedheader =~ s/%WEBBGCOLOR%/$thisWebBGColor/go;
933 $processedheader =~ s/%WEB%/$web/go;
934 $processedheader =~ s/\$ntopics/($ntopics-1)/gse;
935 $processedheader =~ s/\$nhits/($nhits-1)/gse;
936 $processedheader =~ s/\$index/($thits-1)/gs;
937 $processedheader =
938 $this->formatCommon( $processedheader, \%pager_formatting );
939 &$callback( $cbdata, $processedheader );
940 $justdidHeaderOrFooter = 1;
941 }
942
94388451.36ms84732µs if ( defined($separator)
# spent 732µs making 84 calls to Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1336], avg 9µs/call
944 and ( $thits > 1 )
945 and ( $justdidHeaderOrFooter != 1 ) )
946 {
947 &$callback( $cbdata, $separator );
948 }
949
950 ###################Render the result
9518845870µs my $out;
95288453.47ms if ( $formatDefined and ( $format ne '' ) ) {
953
954 #TODO: hack to convert a bad SEARCH format to the one used by getRevInfo..
9558534µs $format =~ s/\$createdate/\$createlongdate/gs;
956
957 #it looks like $isodate in format is equive to $iso in renderRevisionInfo
958 #TODO: clean these 3 hacks up
9598516µs $format =~ s/\$isodate/\$iso/gs;
9608545µs $format =~ s/\%TIME\%/\$date/gs;
9618523µs $format =~ s/\$date/\$longdate/gs;
962
963 #other tmpl based renderings
9648520µs $format =~ s/%WEB%/\$web/go;
9658514µs $format =~ s/%TOPICNAME%/\$topic/go;
9668515µs $format =~ s/%AUTHOR%/\$wikiusername/g;
967
968 # pass search options to summary parser
96985250µs my $searchOptions = {
970 type => $params->{type},
971 wordboundaries => $params->{wordboundaries},
972 casesensitive => $caseSensitive,
973 tokens => $query->{tokens}
974 };
975
976#TODO: why is this not part of the callback? at least the non-result element format strings can be common here.
977#or do i need a formatCommon sub that formatResult can also call.. (which then goes into the callback?
978 $out = $this->formatResult(
979 $format,
980 $info->{tom} || $webObject, #SMELL: horrid hack
981 $text,
982 $searchOptions,
983 {
984 '\$ntopics' => sub { return $ntopics },
985 '\$nhits' => sub { return $nhits },
986 '\$index' => sub { return $thits },
987 '\$item' => sub { return $listItem },
988
989 %pager_formatting,
990
991 #rev1 info
992 #TODO: move the $create* formats into Render::renderRevisionInfo..
993 #which implies moving the infocache's pre-extracted data into the tom obj too.
994 # $out =~ s/\$create(longdate|username|wikiname|wikiusername)/
995 # $infoCache->getRev1Info( $topic, "create$1" )/ges;
996 '\$createlongdate' => sub {
997 return $this->metacache->get( $web, $topic )->{tom}
998 ->getRev1Info("createlongdate");
999 },
1000 '\$createusername' => sub {
1001 return $this->metacache->get( $web, $topic )->{tom}
1002 ->getRev1Info("createusername");
1003 },
1004 '\$createwikiname' => sub {
1005 return $this->metacache->get( $web, $topic )->{tom}
1006 ->getRev1Info("createwikiname");
1007 },
1008 '\$createwikiusername' => sub {
1009 return $this->metacache->get( $web, $topic )->{tom}
1010 ->getRev1Info("createwikiusername");
1011 },
1012
1013 #TODO: hacky bits that need to be moved out of formatResult()
101485250µs
# spent 143µs within Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1014] which was called 85 times, avg 2µs/call: # 85 times (143µs+0s) by Foswiki::Search::formatResult at line 1128, avg 2µs/call
'$revNum' => sub { return ( $info->{revNum} || 0 ); },
101585205µs
# spent 93µs within Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1015] which was called 85 times, avg 1µs/call: # 85 times (93µs+0s) by Foswiki::Search::formatResult at line 1129, avg 1µs/call
'$doBookView' => sub { return $doBookView; },
101685198µs
# spent 88µs within Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1016] which was called 85 times, avg 1µs/call: # 85 times (88µs+0s) by Foswiki::Search::formatResult at line 1130, avg 1µs/call
'$baseWeb' => sub { return $baseWeb; },
101785197µs
# spent 88µs within Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1017] which was called 85 times, avg 1µs/call: # 85 times (88µs+0s) by Foswiki::Search::formatResult at line 1131, avg 1µs/call
'$baseTopic' => sub { return $baseTopic; },
101885195µs
# spent 92µs within Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1018] which was called 85 times, avg 1µs/call: # 85 times (92µs+0s) by Foswiki::Search::formatResult at line 1132, avg 1µs/call
'$newLine' => sub { return $newLine; },
101985191µs
# spent 88µs within Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1019] which was called 85 times, avg 1µs/call: # 85 times (88µs+0s) by Foswiki::Search::formatResult at line 1133, avg 1µs/call
'$separator' => sub { return $separator; },
102085182µs
# spent 79µs within Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1020] which was called 85 times, avg 934ns/call: # 85 times (79µs+0s) by Foswiki::Search::formatResult at line 1134, avg 934ns/call
'$noTotal' => sub { return $noTotal; },
102185183µs
# spent 71µs within Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1021] which was called 85 times, avg 835ns/call: # 85 times (71µs+0s) by Foswiki::Search::formatResult at line 1135, avg 835ns/call
'$paramsHash' => sub { return $params; },
1022 }
1023852.48ms859.65ms );
# spent 9.65ms making 85 calls to Foswiki::Search::formatResult, avg 113µs/call
1024 }
1025 else {
102687601.94ms $out = '';
1027 }
1028
102988459.85ms884514.7ms &$callback( $cbdata, $out );
# spent 13.8ms making 8760 calls to Foswiki::Search::_collate_to_list, avg 2µs/call # spent 916µs making 85 calls to Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1336], avg 11µs/call
1030 } while (@multipleHitLines); # multiple=on loop
1031
1032884520.0ms8845191ms if (
# spent 191ms making 8845 calls to Foswiki::Search::ResultSet::hasNext, avg 22µs/call
1033 ( defined( $params->{pager_skip_results_from} ) )
1034 or ( ( defined( $params->{groupby} ) )
1035 and ( $params->{groupby} ne 'web' ) )
1036 )
1037 {
1038 last if ( $ttopics >= $limit );
1039 }
1040 else {
104188451.67ms if ( $ntopics >= $limit ) {
1042 $infoCache->nextWeb();
1043 }
1044 }
1045 } # end topic loop
1046
1047 # output footer only if hits in web
10484152µs if ( $ntopics == 0 ) {
1049 if ( $zeroResults and not $noTotal ) {
1050 $footer = $params->{footercounter};
1051 }
1052 else {
1053 $footer = '';
1054 }
1055 ##MOVEDUP $webObject = new Foswiki::Meta( $session, $baseWeb );
1056 }
1057 else {
10584126µs if ( ( not $noTotal ) and ( defined( $params->{footercounter} ) ) ) {
1059 $footer .= $params->{footercounter};
1060 }
1061
10624127µs if ( ( defined( $params->{pager} ) ) and ( $params->{pager} eq 'on' ) )
1063 {
1064 $footer .= '$pager';
1065 }
1066 }
10674127µs if ( defined $footer ) {
1068
1069#because $pager contains more $ntopics like format strings, it needs to be expanded first.
107041180µs41293µs $footer = $this->formatCommon( $footer, \%pager_formatting );
# spent 293µs making 41 calls to Foswiki::Search::formatCommon, avg 7µs/call
10714181µs $footer =~ s/\$web/$web/gos; # expand name of web
1072
1073 # $footer =~ s/([^\n])$/$1\n/os; # add new line at end
1074
1075 # output footer of $web
10764121µs $footer =~ s/\$ntopics/$ntopics/gs;
107741113µs $footer =~ s/\$nhits/$nhits/gs;
10784115µs $footer =~ s/\$index/$thits/gs;
1079
1080 #legacy SEARCH counter support
10814123µs $footer =~ s/%NTOPICS%/$ntopics/go;
1082
1083 # $footer =~ s/\n$//os; # remove trailing new line
1084
10854163µs4176µs &$callback( $cbdata, $footer );
# spent 70µs making 40 calls to Foswiki::Search::_collate_to_list, avg 2µs/call # spent 6µs making 1 call to Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1336]
1086 }
1087
108841606µs return ( $ntopics,
1089 ( ( not defined( $params->{_callback} ) ) and ( $nhits >= 0 ) )
1090 ? join( '', @$cbdata )
1091 : '' );
1092}
1093
1094
# spent 293µs within Foswiki::Search::formatCommon which was called 41 times, avg 7µs/call: # 41 times (293µs+0s) by Foswiki::Search::formatResults at line 1070, avg 7µs/call
sub formatCommon {
10954142µs my ( $this, $out, $customKeys ) = @_;
1096
10974131µs my $session = $this->{session};
1098
10994187µs foreach my $key ( keys(%$customKeys) ) {
1100 $out =~ s/$key/&{$customKeys->{$key}}()/ges;
1101 }
110241144µs return $out;
1103}
1104
1105=begin TML
1106
1107---++ ObjectMethod formatResult
1108 * $text can be undefined.
1109 * $searchOptions is an options hash to pass on to the summary parser
1110 * customKeys is a hash of {'$key' => sub {my $item = shift; return value;} }
1111 where $item is a tom object (initially a Foswiki::Meta, but I'd like to be more generic)
1112
1113TODO: i don't really know what we'll need to do about order of processing.
1114TODO: at minimum, the keys need to be sorted by length so that $datatime is processed before $date
1115TODO: need to cater for $summary(params) style too
1116
1117=cut
1118
1119
# spent 9.65ms (7.71+1.94) within Foswiki::Search::formatResult which was called 85 times, avg 113µs/call: # 85 times (7.71ms+1.94ms) by Foswiki::Search::formatResults at line 1023, avg 113µs/call
sub formatResult {
11208597µs my ( $this, $out, $topicObject, $text, $searchOptions, $customKeys ) = @_;
1121
11228536µs my $session = $this->{session};
1123
112485155µs85215µs my $web = $topicObject->web();
# spent 215µs making 85 calls to Foswiki::Meta::web, avg 3µs/call
112585137µs85183µs my $topic = $topicObject->topic();
# spent 183µs making 85 calls to Foswiki::Meta::topic, avg 2µs/call
1126
1127 #TODO: these need to go away.
112885161µs85143µs my $revNum = &{ $customKeys->{'$revNum'} }();
# spent 143µs making 85 calls to Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1014], avg 2µs/call
112985135µs8593µs my $doBookView = &{ $customKeys->{'$doBookView'} }();
# spent 93µs making 85 calls to Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1015], avg 1µs/call
113085124µs8588µs my $baseWeb = &{ $customKeys->{'$baseWeb'} }();
# spent 88µs making 85 calls to Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1016], avg 1µs/call
113185118µs8588µs my $baseTopic = &{ $customKeys->{'$baseTopic'} }();
# spent 88µs making 85 calls to Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1017], avg 1µs/call
113285123µs8592µs my $newLine = &{ $customKeys->{'$newLine'} }();
# spent 92µs making 85 calls to Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1018], avg 1µs/call
113385128µs8588µs my $separator = &{ $customKeys->{'$separator'} }();
# spent 88µs making 85 calls to Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1019], avg 1µs/call
113485116µs8579µs my $noTotal = &{ $customKeys->{'$noTotal'} }();
# spent 79µs making 85 calls to Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1020], avg 934ns/call
113585105µs8571µs my $params = &{ $customKeys->{'$paramsHash'} }();
# spent 71µs making 85 calls to Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1021], avg 835ns/call
113685115µs foreach my $key (
1137 '$revNum', '$doBookView', '$baseWeb', '$baseTopic',
1138 '$newLine', '$separator', '$noTotal', '$paramsHash'
1139 )
1140 {
1141680413µs delete $customKeys->{$key};
1142 }
1143
1144 #SMELL: Because hash order is not predictable, any user supplied
1145 # format which might contain other $format tokens must be expanded first,
1146 # otherwise the results are unpredictable.
1147 # For example, pagerformat contains $ntopics. If $ntopics expands first,
1148 # then pagerformat, then ntopics will remain un-expanded in the output.
1149 # Since key processing order is unpredictable, add any potentially nested
1150 # keys here
11518598µs foreach my $key ('\$pager') {
11528561µs next unless defined $customKeys->{$key};
1153 $out =~ s/$key/&{$customKeys->{$key}}()/ges;
1154 delete $customKeys->{$key};
1155 }
1156
115785260µs foreach my $key ( keys(%$customKeys) ) {
11586802.82ms $out =~ s/$key/&{$customKeys->{$key}}()/ges;
1159 }
1160
1161 #SMELL: hack to stop non-topic based FORMAT's from doing topic code
1162 #TODO: this should be extracted into the customKeys above
1163 # Note that we cannot send a formatted search through renderRevisionInfo
1164 # without expanding tokens we should not because the function also sends
1165 # the input through formatTime and probably other nasty filters
1166 # So we send each token through one by one.
11678538µs if ( defined $topic ) {
1168
11698533µs $out =~ s/\$web/$web/gs;
11708517µs $out =~ s/\$topic\(([^\)]*)\)/Foswiki::Render::breakName(
1171 $topic, $1 )/ges;
117285278µs $out =~ s/\$topic/$topic/gs;
1173 $out =~
11748540µss{(\$rev|\$wikiusername|\$wikiname|\$username|\$createlongdate|\$iso|\$longdate|\$date)}
1175 {$session->renderer->renderRevisionInfo($topicObject, $revNum, $1 )}ges;
1176 }
1177
11788558µs if ( $out =~ m/\$text/ and defined($topic) )
1179 { #TODO: don't muck with text if we're not even a topic
1180 $text = $topicObject->text() unless defined $text;
1181 $text = '' unless defined $text;
1182
1183 if ( $topic eq $session->{topicName} ) {
1184
1185#TODO: extract the diffusion and generalise to whatever MACRO we are processing - anything with a format can loop
1186
1187 # defuse SEARCH in current topic to prevent loop
1188 $text =~ s/%SEARCH{.*?}%/SEARCH{...}/go;
1189 }
1190 $out =~ s/\$text/$text/gos;
1191 }
1192
1193 #TODO: extract the rev
11948558µs my $srev = 'r' . $revNum;
119585172µs36798µs if ( $revNum eq '0' || $revNum eq '1' ) {
# spent 690µs making 12 calls to CGI::span, avg 57µs/call # spent 64µs making 12 calls to Foswiki::I18N::Fallback::maketext, avg 5µs/call # spent 44µs making 12 calls to Foswiki::i18n, avg 4µs/call
1196 $srev = CGI::span( { class => 'foswikiNew' },
1197 ( $session->i18n->maketext('NEW') ) );
1198 }
11998539µs $out =~ s/%REVISION%/$srev/o;
1200
12018533µs if ($doBookView) {
1202
1203 # BookView
1204 $text = $topicObject->text() unless defined $text;
1205 $text = '' unless defined $text;
1206
1207 if ( $web eq $baseWeb && $topic eq $baseTopic ) {
1208
1209 # primitive way to prevent recursion
1210 $text =~ s/%SEARCH/%<nop>SEARCH/g;
1211 }
1212 $text = $topicObject->expandMacros($text);
1213 $text = $topicObject->renderTML($text);
1214
1215 $out =~ s/%TEXTHEAD%/$text/go;
1216
1217 }
1218 else {
1219
1220 #TODO: more topic specific bits
12218534µs if ( defined($topic) ) {
12228531µs $out =~ s/\$summary(?:\(([^\)]*)\))?/
1223 $topicObject->summariseText( $1, $text, $searchOptions )/ges;
12248525µs $out =~ s/\$changes(?:\(([^\)]*)\))?/
1225 $topicObject->summariseChanges(Foswiki::Store::cleanUpRevID($1), $revNum)/ges;
12268522µs $out =~ s/\$formfield\(\s*([^\)]*)\s*\)/
1227 displayFormField( $topicObject, $1 )/ges;
12288523µs $out =~ s/\$parent\(([^\)]*)\)/
1229 Foswiki::Render::breakName(
1230 $topicObject->getParent(), $1 )/ges;
12318529µs $out =~ s/\$parent/$topicObject->getParent()/ges;
12328522µs $out =~ s/\$formname/$topicObject->getFormName()/ges;
12338527µs $out =~ s/\$count\((.*?\s*\.\*)\)/_countPattern( $text, $1 )/ges;
1234
1235 # FIXME: Allow all regex characters but escape them
1236 # Note: The RE requires a .* at the end of a pattern to avoid false positives
1237 # in pattern matching
1238 $out =~
12398526µs s/\$pattern\((.*?\s*\.\*)\)/_extractPattern( $text, $1 )/ges;
1240 }
12418514µs $out =~ s/\r?\n/$newLine/gos if ($newLine);
1242
1243 # If separator is not defined we default to \n
1244 # We also add new line after last search result but before footer
1245 # when separator is not defined for backwards compatibility
1246 # per Item1773 / SearchSeparatorDefaultHeaderFooter
12478521µs if ( !defined($separator) ) {
1248 unless ( $noTotal && !$params->{formatdefined} ) {
1249 $out =~ s/([^\n])$/$1\n/s;
1250 }
1251 }
1252 }
1253
1254#see http://foswiki.org/Tasks/Item2371 - needs unit test exploration
1255#the problem is that when I separated the formating from the searching, I set the format string to what is in the template,
1256#and thus here, format is always set.
1257# elsif ($noSummary) {
1258# #TODO: i think that means I've broken SEARCH{nosummary=on" with no format specified
1259# $out =~ s/%TEXTHEAD%//go;
1260# $out =~ s/&nbsp;//go;
1261# }
1262# else {
1263# #SEARCH with no format and nonoise="off" or nosummary="off"
1264# #TODO: BROKEN, need to fix the meaning of nosummary and nonoise in SEARCH
1265# # regular search view
1266# $text = $info->{tom}->summariseText( '', $text );
1267# $out =~ s/%TEXTHEAD%/$text/go;
1268# }
126985392µs return $out;
1270}
1271
1272=begin TML
1273
1274---++ StaticMethod displayFormField( $meta, $args ) -> $text
1275
1276Parse the arguments to a $formfield specification and extract
1277the relevant formfield from the given meta data.
1278
1279 * =args= string containing name of form field
1280
1281In addition to the name of a field =args= can be appended with a commas
1282followed by a string format (\d+)([,\s*]\.\.\.)?). This supports the formatted
1283search function $formfield and is used to shorten the returned string or a
1284hyphenated string.
1285
1286=cut
1287
1288sub displayFormField {
1289 my ( $meta, $args ) = @_;
1290
1291 my ( $name, @params ) = split( /,\s*/, $args );
1292 my $displayedVal = 0; # default is to show the unmapped value
1293 my $breakArgs = '';
1294 if (@params) {
1295 if ( $params[0] eq 'display' ) {
1296
1297 # The displayed value is required
1298 $displayedVal = 1;
1299 shift @params;
1300 }
1301 $breakArgs = join( ',', @params );
1302 }
1303
1304 # SMELL: this is a *terrible* idea. Not only does it munge the result
1305 # so it can only be used for display, it also munges it such that it
1306 # can't be repaired by the options on %SEARCH. 'nomap' goes some
1307 # way to curing the problem, but it's still not ideal :-(
1308 return $meta->renderFormFieldForDisplay(
1309 $name, '$value',
1310 {
1311 break => $breakArgs,
1312 protectdollar => 1,
1313 showhidden => 1,
1314 display => $displayedVal
1315 }
1316 );
1317}
1318
1319#my ($callback, $cbdata) = setup_callback(\%params, $baseWebObject);
1320
# spent 526µs within Foswiki::Search::setup_callback which was called 82 times, avg 6µs/call: # 41 times (348µs+0s) by Foswiki::Search::formatResults at line 596, avg 8µs/call # 41 times (178µs+0s) by Foswiki::Search::searchWeb at line 246, avg 4µs/call
sub setup_callback {
13218251µs my ( $params, $webObj ) = @_;
1322
13238253µs my $callback = $params->{_callback};
13248228µs my $cbdata = $params->{_cbdata};
1325
1326 #add in the rendering..
13278269µs if ( defined( $params->{_callback} ) ) {
1328
# spent 1.65ms (1.24+418µs) within Foswiki::Search::__ANON__[/var/www/foswiki11/lib/Foswiki/Search.pm:1336] which was called 170 times, avg 10µs/call: # 85 times (661µs+255µs) by Foswiki::Search::formatResults at line 1029, avg 11µs/call # 84 times (570µs+161µs) by Foswiki::Search::formatResults at line 943, avg 9µs/call # once (4µs+1µs) by Foswiki::Search::formatResults at line 1085
$callback = sub {
132917058µs my $cbdata = shift;
133017043µs my $text = shift;
1331170101µs my $oldcallback = $params->{_callback};
1332
133317029µs $text = $webObj->renderTML($text) if defined($webObj);
1334170112µs $text =~ s|</*nop/*>||goi; # remove <nop> tag
1335170650µs170418µs &$oldcallback( $cbdata, $text );
# spent 418µs making 170 calls to Foswiki::Users::TopicUserMapping::_collateGroups, avg 2µs/call
1336213µs };
1337 }
1338 else {
13398046µs $cbdata = $params->{_cbdata} = [] unless ( defined($cbdata) );
13408056µs $callback = \&_collate_to_list;
1341 }
134282268µs return ( $callback, $cbdata );
1343}
1344
1345# callback for search function to collate to list
1346
# spent 13.9ms within Foswiki::Search::_collate_to_list which was called 8800 times, avg 2µs/call: # 8760 times (13.8ms+0s) by Foswiki::Search::formatResults at line 1029, avg 2µs/call # 40 times (70µs+0s) by Foswiki::Search::formatResults at line 1085, avg 2µs/call
sub _collate_to_list {
134788002.06ms my $ref = shift;
1348
1349880028.5ms push( @$ref, @_ );
1350}
1351
135212µs1;
1353__END__