Filename | /var/www/foswikidev/core/lib/Foswiki/Prefs.pm |
Statements | Executed 10676 statements in 18.4ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1405 | 23 | 12 | 23.3ms | 29.4ms | getPreference | Foswiki::Prefs::
693 | 7 | 2 | 3.30ms | 3.30ms | setInternalPreferences | Foswiki::Prefs::
112 | 1 | 1 | 1.64ms | 19.2ms | loadPreferences | Foswiki::Prefs::
1 | 1 | 1 | 1.09ms | 1.15ms | BEGIN@77 | Foswiki::Prefs::
111 | 1 | 1 | 848µs | 16.5ms | _getWebPrefsObj | Foswiki::Prefs::
54 | 7 | 1 | 627µs | 48.6ms | _getBackend | Foswiki::Prefs::
9 | 2 | 2 | 594µs | 6.20ms | pushTopicContext | Foswiki::Prefs::
1 | 1 | 1 | 348µs | 393µs | BEGIN@78 | Foswiki::Prefs::
1 | 1 | 1 | 344µs | 883µs | BEGIN@76 | Foswiki::Prefs::
8 | 1 | 1 | 250µs | 2.68ms | popTopicContext | Foswiki::Prefs::
16 | 1 | 1 | 247µs | 14.9ms | _pushWebInStack | Foswiki::Prefs::
1 | 1 | 1 | 236µs | 861µs | finish | Foswiki::Prefs::
9 | 2 | 2 | 120µs | 324µs | setSessionPreferences | Foswiki::Prefs::
7 | 1 | 1 | 78µs | 11.8ms | setPluginPreferences | Foswiki::Prefs::
1 | 1 | 1 | 60µs | 1.16ms | new | Foswiki::Prefs::
1 | 1 | 1 | 17µs | 817µs | loadSitePreferences | Foswiki::Prefs::
1 | 1 | 1 | 13µs | 27µs | BEGIN@2 | Foswiki::
1 | 1 | 1 | 13µs | 18.7ms | loadDefaultPreferences | Foswiki::Prefs::
1 | 1 | 1 | 11µs | 35µs | BEGIN@75 | Foswiki::Prefs::
1 | 1 | 1 | 10µs | 734µs | setUserPreferences | Foswiki::Prefs::
1 | 1 | 1 | 10µs | 14µs | BEGIN@3 | Foswiki::
1 | 1 | 1 | 4µs | 4µs | BEGIN@79 | Foswiki::Prefs::
1 | 1 | 1 | 4µs | 4µs | BEGIN@5 | Foswiki::
0 | 0 | 0 | 0s | 0s | stringify | Foswiki::Prefs::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # See bottom of file for license and copyright information | ||||
2 | 2 | 26µs | 2 | 41µs | # spent 27µs (13+14) within Foswiki::BEGIN@2 which was called:
# once (13µs+14µs) by Foswiki::BEGIN@645 at line 2 # spent 27µs making 1 call to Foswiki::BEGIN@2
# spent 14µs making 1 call to strict::import |
3 | 2 | 44µs | 2 | 18µs | # spent 14µs (10+4) within Foswiki::BEGIN@3 which was called:
# once (10µs+4µs) by Foswiki::BEGIN@645 at line 3 # spent 14µs making 1 call to Foswiki::BEGIN@3
# spent 4µs making 1 call to warnings::import |
4 | |||||
5 | # spent 4µs within Foswiki::BEGIN@5 which was called:
# once (4µs+0s) by Foswiki::BEGIN@645 at line 10 | ||||
6 | 1 | 5µs | if ( $Foswiki::cfg{UseLocale} ) { | ||
7 | require locale; | ||||
8 | import locale(); | ||||
9 | } | ||||
10 | 1 | 61µs | 1 | 4µs | } # spent 4µs making 1 call to Foswiki::BEGIN@5 |
11 | |||||
12 | =begin TML | ||||
13 | |||||
14 | ---+ package Foswiki::Prefs | ||||
15 | |||||
16 | Preferences are set in topics, using either 'Set' lines embedded in the | ||||
17 | topic text, or via PREFERENCE meta-data attached to the topic. A preference | ||||
18 | value has four _scopes_: | ||||
19 | * _Global_ scope | ||||
20 | * _Local_ scope | ||||
21 | * _Web_ scope | ||||
22 | * _Topic_ scope | ||||
23 | |||||
24 | In _global_ scope, the value of a preference is determined by examining | ||||
25 | settings of the variable at different levels; default preferences, site level, | ||||
26 | parent web level, web level, user level, and topic level. To determine a | ||||
27 | preference value in global scope, you have to know what topic the topic is | ||||
28 | referenced in, to provide the scope for the request. | ||||
29 | |||||
30 | A preference may be optionally defined in _Local_ scope, in which case the | ||||
31 | topic definition of the variable is always taken when it is referenced in the | ||||
32 | topic where it is defined. This is a special case to deal with the case where a | ||||
33 | preference has to have a different value in the defining topic. | ||||
34 | |||||
35 | Values in global and local scope are accessed using =getPreference= | ||||
36 | |||||
37 | _Web_ scope is used by web access controls. Subwebs inherint access controls | ||||
38 | from parent webs and only from parent webs. Global and Local scopes are | ||||
39 | disconsidered. | ||||
40 | |||||
41 | The final scope is _topic_ scope. In this scope, the value of the preference is | ||||
42 | taken directly from the contents of the topic, and is not overridden by wider | ||||
43 | scopes. Topic scope is used for topic access controls. | ||||
44 | |||||
45 | Because the highest cost in evaluating preferences is reading the individual | ||||
46 | topics, preferences read from a topic are cached. | ||||
47 | |||||
48 | An object of type Foswiki::Prefs is a singleton that provides an interface to | ||||
49 | this cache. Normally the cache is repopulated for each request, though it would | ||||
50 | be feasible to cache it on disc if some invalidation mechanism were available | ||||
51 | to deal with topic changes. | ||||
52 | |||||
53 | This mechanism is composed by a front-end (implemented by this class) that | ||||
54 | deals with preferences logic and back-end objects that provide access to | ||||
55 | preferences values. There is one back-end for each topic (Web preferences are | ||||
56 | back-ends correspondind to the WebPreferences topic). Additionaly, there is a | ||||
57 | back-end object for session preferences. Each context has its own session | ||||
58 | preferences and thus its own session back-end object. | ||||
59 | |||||
60 | Preferences are like a stack: there are many levels and higher levels have | ||||
61 | precedence over lower levels. It's also needed to push a context and pop to the | ||||
62 | earlier state. It would be easy to implement this stack, but then we would have | ||||
63 | a problem: to get the value of a preference we would need to scan each level | ||||
64 | and it's slow, so we need some fast mechanism to know in which level a | ||||
65 | preference is defined. Or we could copy the values from lower leves to higher | ||||
66 | ones and override the preferences defined at that level. This later approach | ||||
67 | wastes memory. This implementation picks the former and we use bitstrings and | ||||
68 | some maths to accomplish that. It's also flexible and it doesn't matter how | ||||
69 | preferences are stored. | ||||
70 | |||||
71 | =cut | ||||
72 | |||||
73 | package Foswiki::Prefs; | ||||
74 | |||||
75 | 2 | 26µs | 2 | 60µs | # spent 35µs (11+24) within Foswiki::Prefs::BEGIN@75 which was called:
# once (11µs+24µs) by Foswiki::BEGIN@645 at line 75 # spent 35µs making 1 call to Foswiki::Prefs::BEGIN@75
# spent 24µs making 1 call to Exporter::import |
76 | 2 | 96µs | 1 | 883µs | # spent 883µs (344+539) within Foswiki::Prefs::BEGIN@76 which was called:
# once (344µs+539µs) by Foswiki::BEGIN@645 at line 76 # spent 883µs making 1 call to Foswiki::Prefs::BEGIN@76 |
77 | 2 | 98µs | 1 | 1.15ms | # spent 1.15ms (1.09+54µs) within Foswiki::Prefs::BEGIN@77 which was called:
# once (1.09ms+54µs) by Foswiki::BEGIN@645 at line 77 # spent 1.15ms making 1 call to Foswiki::Prefs::BEGIN@77 |
78 | 2 | 87µs | 1 | 393µs | # spent 393µs (348+45) within Foswiki::Prefs::BEGIN@78 which was called:
# once (348µs+45µs) by Foswiki::BEGIN@645 at line 78 # spent 393µs making 1 call to Foswiki::Prefs::BEGIN@78 |
79 | 2 | 1.54ms | 1 | 4µs | # spent 4µs within Foswiki::Prefs::BEGIN@79 which was called:
# once (4µs+0s) by Foswiki::BEGIN@645 at line 79 # spent 4µs making 1 call to Foswiki::Prefs::BEGIN@79 |
80 | |||||
81 | =begin TML | ||||
82 | |||||
83 | ---++ ClassMethod new( $session ) | ||||
84 | |||||
85 | Creates a new Prefs object. | ||||
86 | |||||
87 | =cut | ||||
88 | |||||
89 | # spent 1.16ms (60µs+1.10) within Foswiki::Prefs::new which was called:
# once (60µs+1.10ms) by Foswiki::new at line 2098 of /var/www/foswikidev/core/lib/Foswiki.pm | ||||
90 | 1 | 2µs | my ( $proto, $session ) = @_; | ||
91 | 1 | 1µs | my $class = ref($proto) || $proto; | ||
92 | 1 | 8µs | 1 | 13µs | my $this = { # spent 13µs making 1 call to Foswiki::Prefs::Stack::new |
93 | 'main' => Foswiki::Prefs::Stack->new(), # Main preferences stack | ||||
94 | 'paths' => {}, # Map paths to backend objects | ||||
95 | 'contexts' => [], # Store the main levels corresponding to contexts | ||||
96 | 'prefix' => [], # Map level => prefix uesed | ||||
97 | # (plugins prefix prefs with PLUGINNAME_) | ||||
98 | 'webprefs' => {}, # Foswiki::Prefs::Web objs, used to get web prefs | ||||
99 | 'internals' => {}, # Store internal preferences | ||||
100 | 'session' => $session, | ||||
101 | }; | ||||
102 | |||||
103 | 1 | 33µs | eval "use $Foswiki::cfg{Store}{PrefsBackend} ()"; # spent 77µs executing statements in string eval # includes 459µs spent executing 1 call to 1 sub defined therein. | ||
104 | 1 | 500ns | die $@ if $@; | ||
105 | |||||
106 | 1 | 11µs | return bless $this, $class; | ||
107 | } | ||||
108 | |||||
109 | =begin TML | ||||
110 | |||||
111 | ---++ ObjectMethod finish() | ||||
112 | Break circular references. | ||||
113 | |||||
114 | =cut | ||||
115 | |||||
116 | # Note to developers; please undef *all* fields in the object explicitly, | ||||
117 | # whether they are references or not. That way this method is "golden | ||||
118 | # documentation" of the live fields in the object. | ||||
119 | # spent 861µs (236+625) within Foswiki::Prefs::finish which was called:
# once (236µs+625µs) by Foswiki::finish at line 2488 of /var/www/foswikidev/core/lib/Foswiki.pm | ||||
120 | 1 | 500ns | my $this = shift; | ||
121 | |||||
122 | 1 | 42µs | 1 | 307µs | $this->{main}->finish() if $this->{main}; # spent 307µs making 1 call to Foswiki::Prefs::Stack::finish |
123 | 1 | 1µs | undef $this->{main}; | ||
124 | 1 | 3µs | undef $this->{prefix}; | ||
125 | 1 | 400ns | undef $this->{session}; | ||
126 | 1 | 2µs | undef $this->{contexts}; | ||
127 | 1 | 7µs | if ( $this->{paths} ) { | ||
128 | foreach my $back ( values %{ $this->{paths} } ) { | ||||
129 | 28 | 95µs | 28 | 92µs | $back->finish(); # spent 92µs making 28 calls to Foswiki::Prefs::TopicRAM::finish, avg 3µs/call |
130 | } | ||||
131 | } | ||||
132 | 1 | 10µs | undef $this->{paths}; | ||
133 | 1 | 5µs | if ( $this->{webprefs} ) { | ||
134 | foreach my $webStack ( values %{ $this->{webprefs} } ) { | ||||
135 | 17 | 23µs | 17 | 226µs | $webStack->finish(); # spent 226µs making 17 calls to Foswiki::Prefs::Web::finish, avg 13µs/call |
136 | } | ||||
137 | } | ||||
138 | 1 | 6µs | undef $this->{webprefs}; | ||
139 | 1 | 4µs | undef $this->{internals}; | ||
140 | } | ||||
141 | |||||
142 | # Get a backend object corresponding to the given $web,$topic | ||||
143 | # spent 48.6ms (627µs+48.0) within Foswiki::Prefs::_getBackend which was called 54 times, avg 900µs/call:
# 18 times (176µs+2.38ms) by Foswiki::Prefs::pushTopicContext at line 283, avg 142µs/call
# 17 times (241µs+13.5ms) by Foswiki::Prefs::_pushWebInStack at line 168, avg 810µs/call
# 9 times (74µs+837µs) by Foswiki::Prefs::pushTopicContext at line 286, avg 101µs/call
# 7 times (91µs+11.4ms) by Foswiki::Prefs::setPluginPreferences at line 334, avg 1.65ms/call
# once (22µs+18.4ms) by Foswiki::Prefs::loadDefaultPreferences at line 366
# once (12µs+728µs) by Foswiki::Prefs::loadSitePreferences at line 384
# once (12µs+695µs) by Foswiki::Prefs::setUserPreferences at line 352 | ||||
144 | 54 | 20µs | my $this = shift; | ||
145 | |||||
146 | 54 | 139µs | 54 | 547µs | my $metaObject = Foswiki::Meta->new( $this->{session}, @_ ); # spent 547µs making 54 calls to Foswiki::Meta::new, avg 10µs/call |
147 | 54 | 77µs | 54 | 130µs | my $path = $metaObject->getPath(); # spent 130µs making 54 calls to Foswiki::Meta::getPath, avg 2µs/call |
148 | 54 | 166µs | 28 | 47.3ms | unless ( exists $this->{paths}{$path} ) { # spent 47.3ms making 28 calls to Foswiki::Prefs::TopicRAM::new, avg 1.69ms/call |
149 | $this->{paths}{$path} = | ||||
150 | $Foswiki::cfg{Store}{PrefsBackend}->new($metaObject); | ||||
151 | } | ||||
152 | 54 | 162µs | return $this->{paths}{$path}; | ||
153 | } | ||||
154 | |||||
155 | # Given a (sub)web and a stack object, push the (sub)web on the stack, | ||||
156 | # considering that part of the (sub)web may already be in the stack. This is | ||||
157 | # used to build, for example, Web/Subweb/WebA stack based on Web/Subweb or Web | ||||
158 | # stack. | ||||
159 | # spent 14.9ms (247µs+14.7) within Foswiki::Prefs::_pushWebInStack which was called 16 times, avg 933µs/call:
# 16 times (247µs+14.7ms) by Foswiki::Prefs::_getWebPrefsObj at line 204, avg 933µs/call | ||||
160 | 16 | 10µs | my ( $this, $stack, $web ) = @_; | ||
161 | 16 | 34µs | my @webPath = split( /[\/\.]+/, $web ); | ||
162 | 16 | 5µs | my $subWeb = ''; | ||
163 | 16 | 29µs | 16 | 21µs | $subWeb = join '/', splice @webPath, 0, $stack->size(); # spent 21µs making 16 calls to Foswiki::Prefs::Stack::size, avg 1µs/call |
164 | 16 | 2µs | my $back; | ||
165 | 16 | 44µs | foreach (@webPath) { | ||
166 | 17 | 7µs | $subWeb .= '/' if $subWeb; | ||
167 | 17 | 6µs | $subWeb .= $_; | ||
168 | 17 | 26µs | 17 | 13.8ms | $back = $this->_getBackend( $subWeb, $Foswiki::cfg{WebPrefsTopicName} ); # spent 13.8ms making 17 calls to Foswiki::Prefs::_getBackend, avg 810µs/call |
169 | 17 | 33µs | 17 | 888µs | $stack->newLevel($back); # spent 888µs making 17 calls to Foswiki::Prefs::Stack::newLevel, avg 52µs/call |
170 | } | ||||
171 | } | ||||
172 | |||||
173 | # Returns a Foswiki::Prefs::Web object. It consider the already existing | ||||
174 | # objects and build a new one only if it doesn't exist. And even if it doesn't | ||||
175 | # exist, consider existing ones to speedup the construction. Example: | ||||
176 | # Web/SubWeb already exists and we want Web/Subweb/WebA. Then we just push | ||||
177 | # WebA. If, instead, Web/Subweb/WebB exists, then we clone tha stack up to | ||||
178 | # Web/Subweb and push WebA on it. | ||||
179 | # spent 16.5ms (848µs+15.7) within Foswiki::Prefs::_getWebPrefsObj which was called 111 times, avg 149µs/call:
# 111 times (848µs+15.7ms) by Foswiki::Prefs::loadPreferences at line 237, avg 149µs/call | ||||
180 | 111 | 71µs | my ( $this, $web ) = @_; | ||
181 | 111 | 37µs | my ( $stack, $level ); | ||
182 | |||||
183 | 111 | 340µs | if ( exists $this->{webprefs}{$web} ) { | ||
184 | return $this->{webprefs}{$web}; | ||||
185 | } | ||||
186 | |||||
187 | 16 | 2µs | my $part; | ||
188 | 16 | 54µs | 16 | 79µs | $stack = Foswiki::Prefs::Stack->new(); # spent 79µs making 16 calls to Foswiki::Prefs::Stack::new, avg 5µs/call |
189 | 16 | 52µs | my @path = split /[\/\.]+/, $web; | ||
190 | 16 | 9µs | my @websToAdd = ( pop @path ); | ||
191 | 16 | 11µs | while ( @path > 0 ) { | ||
192 | 9 | 8µs | $part = join( '/', @path ); | ||
193 | 9 | 8µs | if ( exists $this->{webprefs}{$part} ) { | ||
194 | 8 | 4µs | my $base = $this->{webprefs}{$part}; | ||
195 | 8 | 33µs | 16 | 596µs | $stack = # spent 542µs making 7 calls to Foswiki::Prefs::Web::cloneStack, avg 77µs/call
# spent 51µs making 8 calls to Foswiki::Prefs::Web::isInTopOfStack, avg 6µs/call
# spent 2µs making 1 call to Foswiki::Prefs::Web::stack |
196 | $base->isInTopOfStack() | ||||
197 | ? $base->stack() | ||||
198 | : $base->cloneStack( scalar(@path) - 1 ); | ||||
199 | 8 | 5µs | last; | ||
200 | } | ||||
201 | 1 | 2µs | unshift @websToAdd, pop @path; | ||
202 | } | ||||
203 | |||||
204 | 16 | 24µs | 16 | 14.9ms | $this->_pushWebInStack( $stack, $web ); # spent 14.9ms making 16 calls to Foswiki::Prefs::_pushWebInStack, avg 933µs/call |
205 | 16 | 12µs | $part = join( '/', @path ); | ||
206 | 16 | 6µs | $level = scalar(@path); | ||
207 | 16 | 8µs | foreach (@websToAdd) { | ||
208 | 17 | 7µs | $part .= '/' if $part; | ||
209 | 17 | 5µs | $part .= $_; | ||
210 | 17 | 90µs | 17 | 82µs | $this->{webprefs}{$part} = Foswiki::Prefs::Web->new( $stack, $level++ ); # spent 82µs making 17 calls to Foswiki::Prefs::Web::new, avg 5µs/call |
211 | } | ||||
212 | 16 | 42µs | return $this->{webprefs}{$web}; | ||
213 | } | ||||
214 | |||||
215 | =begin TML | ||||
216 | |||||
217 | ---++ ObjectMethod loadPreferences( $topicObject ) -> $back | ||||
218 | |||||
219 | Invoked from Foswiki::Meta to load the preferences into the preferences | ||||
220 | cache. used as part of the lazy-loading of preferences. | ||||
221 | |||||
222 | Web preferences are loaded from the {WebPrefsTopicName}. | ||||
223 | |||||
224 | =cut | ||||
225 | |||||
226 | # spent 19.2ms (1.64+17.6) within Foswiki::Prefs::loadPreferences which was called 112 times, avg 172µs/call:
# 112 times (1.64ms+17.6ms) by Foswiki::Meta::getPreference at line 677 of /var/www/foswikidev/core/lib/Foswiki/Meta.pm, avg 172µs/call | ||||
227 | 112 | 60µs | my ( $this, $topicObject ) = @_; | ||
228 | |||||
229 | 112 | 202µs | 112 | 270µs | my $path = $topicObject->getPath(); # spent 270µs making 112 calls to Foswiki::Meta::getPath, avg 2µs/call |
230 | |||||
231 | # $topicObject->session->logger->log( 'debug', | ||||
232 | # "Loading preferences for $path\n" ) | ||||
233 | # if DEBUG; | ||||
234 | |||||
235 | 112 | 16µs | my $obj; | ||
236 | |||||
237 | 112 | 638µs | 446 | 17.3ms | if ( $topicObject->topic() ) { # spent 16.5ms making 111 calls to Foswiki::Prefs::_getWebPrefsObj, avg 149µs/call
# spent 302µs making 222 calls to Foswiki::Meta::web, avg 1µs/call
# spent 289µs making 1 call to Foswiki::Prefs::TopicRAM::new
# spent 170µs making 112 calls to Foswiki::Meta::topic, avg 2µs/call |
238 | $obj = $Foswiki::cfg{Store}{PrefsBackend}->new($topicObject); | ||||
239 | } | ||||
240 | elsif ( $topicObject->web() ) { | ||||
241 | $obj = $this->_getWebPrefsObj( $topicObject->web() ); | ||||
242 | } | ||||
243 | elsif ( $Foswiki::cfg{LocalSitePreferences} ) { | ||||
244 | my ( $web, $topic ) = | ||||
245 | $this->{session} | ||||
246 | ->normalizeWebTopicName( undef, $Foswiki::cfg{LocalSitePreferences} ); | ||||
247 | |||||
248 | # Use the site preferences | ||||
249 | $obj = $this->_getBackend( $web, $topic ); | ||||
250 | } | ||||
251 | |||||
252 | 112 | 265µs | return $obj; | ||
253 | } | ||||
254 | |||||
255 | =begin TML | ||||
256 | |||||
257 | ---++ ObjectMethod pushTopicContext( $web, $topic ) | ||||
258 | |||||
259 | Reconfigures the preferences so that general preference values appear | ||||
260 | to come from $web.$topic. The topic context can be popped again using | ||||
261 | popTopicContext. | ||||
262 | |||||
263 | =cut | ||||
264 | |||||
265 | # spent 6.20ms (594µs+5.61) within Foswiki::Prefs::pushTopicContext which was called 9 times, avg 689µs/call:
# 8 times (514µs+2.36ms) by Foswiki::_includeTopic at line 176 of /var/www/foswikidev/core/lib/Foswiki/Macros/INCLUDE.pm, avg 359µs/call
# once (80µs+3.24ms) by Foswiki::new at line 2255 of /var/www/foswikidev/core/lib/Foswiki.pm | ||||
266 | 9 | 7µs | my ( $this, $web, $topic ) = @_; | ||
267 | |||||
268 | 9 | 5µs | my $stack = $this->{main}; | ||
269 | 9 | 1µs | my %internals; | ||
270 | 9 | 78µs | while ( my ( $k, $v ) = each %{ $this->{internals} } ) { | ||
271 | $internals{$k} = $v; | ||||
272 | } | ||||
273 | push( | ||||
274 | 9 | 35µs | 9 | 15µs | @{ $this->{contexts} }, # spent 15µs making 9 calls to Foswiki::Prefs::Stack::size, avg 2µs/call |
275 | { internals => \%internals, level => $stack->size() - 1 } | ||||
276 | ); | ||||
277 | 9 | 33µs | my @webPath = split( /[\/\.]+/, $web ); | ||
278 | 9 | 2µs | my $subWeb = ''; | ||
279 | 9 | 1µs | my $back; | ||
280 | 9 | 9µs | foreach (@webPath) { | ||
281 | 18 | 5µs | $subWeb .= '/' if $subWeb; | ||
282 | 18 | 4µs | $subWeb .= $_; | ||
283 | 18 | 38µs | 18 | 2.56ms | $back = $this->_getBackend( $subWeb, $Foswiki::cfg{WebPrefsTopicName} ); # spent 2.56ms making 18 calls to Foswiki::Prefs::_getBackend, avg 142µs/call |
284 | 18 | 30µs | 18 | 1.07ms | $stack->newLevel($back); # spent 1.07ms making 18 calls to Foswiki::Prefs::Stack::newLevel, avg 60µs/call |
285 | } | ||||
286 | 9 | 13µs | 9 | 911µs | $back = $this->_getBackend( $web, $topic ); # spent 911µs making 9 calls to Foswiki::Prefs::_getBackend, avg 101µs/call |
287 | 9 | 11µs | 9 | 102µs | $stack->newLevel($back); # spent 102µs making 9 calls to Foswiki::Prefs::Stack::newLevel, avg 11µs/call |
288 | 9 | 38µs | 18 | 273µs | $stack->newLevel( Foswiki::Prefs::HASH->new() ); # spent 154µs making 9 calls to Foswiki::Prefs::HASH::new, avg 17µs/call
# spent 119µs making 9 calls to Foswiki::Prefs::Stack::newLevel, avg 13µs/call |
289 | |||||
290 | 9 | 158µs | 52 | 673µs | while ( my ( $k, $v ) = each %{ $this->{internals} } ) { # spent 673µs making 52 calls to Foswiki::Prefs::Stack::insert, avg 13µs/call |
291 | $stack->insert( 'Set', $k, $v ); | ||||
292 | } | ||||
293 | |||||
294 | } | ||||
295 | |||||
296 | =begin TML | ||||
297 | |||||
298 | ---+++ popTopicContext() | ||||
299 | |||||
300 | Returns the context to the state it was in before the | ||||
301 | =pushTopicContext= was last called. | ||||
302 | |||||
303 | =cut | ||||
304 | |||||
305 | # spent 2.68ms (250µs+2.43) within Foswiki::Prefs::popTopicContext which was called 8 times, avg 335µs/call:
# 8 times (250µs+2.43ms) by Foswiki::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Macros/INCLUDE.pm:356] at line 354 of /var/www/foswikidev/core/lib/Foswiki/Macros/INCLUDE.pm, avg 335µs/call | ||||
306 | 8 | 2µs | my $this = shift; | ||
307 | 8 | 4µs | my $stack = $this->{main}; | ||
308 | 8 | 5µs | my $context = pop( @{ $this->{contexts} } ); | ||
309 | 8 | 4µs | my $level = $context->{level}; | ||
310 | 8 | 57µs | while ( my ( $k, $v ) = each %{ $context->{internals} } ) { | ||
311 | $this->{internals}{$k} = $v; | ||||
312 | } | ||||
313 | 8 | 53µs | 8 | 2.37ms | $stack->restore($level); # spent 2.37ms making 8 calls to Foswiki::Prefs::Stack::restore, avg 297µs/call |
314 | 8 | 5µs | splice @{ $this->{prefix} }, $level + 1 if @{ $this->{prefix} } > $level; | ||
315 | |||||
316 | # Note: this used to get the web from (-3) - but that only gives the | ||||
317 | # last component of the web path, and fails if the web name is empty. | ||||
318 | 8 | 27µs | 16 | 29µs | my $toRef = $stack->backAtLevel(-2)->topicObject; # spent 15µs making 8 calls to Foswiki::Prefs::Stack::backAtLevel, avg 2µs/call
# spent 14µs making 8 calls to Foswiki::Prefs::TopicRAM::topicObject, avg 2µs/call |
319 | 8 | 49µs | 16 | 28µs | return ( $toRef->web(), $toRef->topic() ); # spent 16µs making 8 calls to Foswiki::Meta::web, avg 2µs/call
# spent 12µs making 8 calls to Foswiki::Meta::topic, avg 2µs/call |
320 | } | ||||
321 | |||||
322 | =begin TML | ||||
323 | |||||
324 | ---++ ObjectMethod setPluginPreferences( $web, $plugin ) | ||||
325 | |||||
326 | Reads preferences from the given plugin topic and injects them into | ||||
327 | the plugin preferences cache. Preferences cannot be finalised in | ||||
328 | plugin topics. | ||||
329 | |||||
330 | =cut | ||||
331 | |||||
332 | # spent 11.8ms (78µs+11.8) within Foswiki::Prefs::setPluginPreferences which was called 7 times, avg 1.69ms/call:
# 7 times (78µs+11.8ms) by Foswiki::Plugin::registerSettings at line 232 of /var/www/foswikidev/core/lib/Foswiki/Plugin.pm, avg 1.69ms/call | ||||
333 | 7 | 5µs | my ( $this, $web, $plugin ) = @_; | ||
334 | 7 | 8µs | 7 | 11.5ms | my $back = $this->_getBackend( $web, $plugin ); # spent 11.5ms making 7 calls to Foswiki::Prefs::_getBackend, avg 1.65ms/call |
335 | 7 | 7µs | my $prefix = uc($plugin) . '_'; | ||
336 | 7 | 3µs | my $stack = $this->{main}; | ||
337 | 7 | 10µs | 7 | 205µs | $stack->newLevel( $back, $prefix ); # spent 205µs making 7 calls to Foswiki::Prefs::Stack::newLevel, avg 29µs/call |
338 | 7 | 33µs | 7 | 11µs | $this->{prefix}->[ $stack->size() - 1 ] = $prefix; # spent 11µs making 7 calls to Foswiki::Prefs::Stack::size, avg 2µs/call |
339 | } | ||||
340 | |||||
341 | =begin TML | ||||
342 | |||||
343 | ---++ ObjectMethod setUserPreferences( $wikiname ) | ||||
344 | |||||
345 | Reads preferences from the given user topic and pushes them to the preferences | ||||
346 | stack. | ||||
347 | |||||
348 | =cut | ||||
349 | |||||
350 | # spent 734µs (10+725) within Foswiki::Prefs::setUserPreferences which was called:
# once (10µs+725µs) by Foswiki::new at line 2251 of /var/www/foswikidev/core/lib/Foswiki.pm | ||||
351 | 1 | 1µs | my ( $this, $wn ) = @_; | ||
352 | 1 | 1µs | 1 | 707µs | my $back = $this->_getBackend( $Foswiki::cfg{UsersWebName}, $wn ); # spent 707µs making 1 call to Foswiki::Prefs::_getBackend |
353 | 1 | 4µs | 1 | 18µs | $this->{main}->newLevel($back); # spent 18µs making 1 call to Foswiki::Prefs::Stack::newLevel |
354 | } | ||||
355 | |||||
356 | =begin TML | ||||
357 | |||||
358 | ---++ ObjectMethod loadDefaultPreferences() | ||||
359 | |||||
360 | Add default preferences to this preferences stack. | ||||
361 | |||||
362 | =cut | ||||
363 | |||||
364 | # spent 18.7ms (13µs+18.7) within Foswiki::Prefs::loadDefaultPreferences which was called:
# once (13µs+18.7ms) by Foswiki::new at line 2220 of /var/www/foswikidev/core/lib/Foswiki.pm | ||||
365 | 1 | 600ns | my $this = shift; | ||
366 | 1 | 3µs | 1 | 18.4ms | my $back = $this->_getBackend( $Foswiki::cfg{SystemWebName}, # spent 18.4ms making 1 call to Foswiki::Prefs::_getBackend |
367 | $Foswiki::cfg{SitePrefsTopicName} ); | ||||
368 | 1 | 6µs | 1 | 333µs | $this->{main}->newLevel($back); # spent 333µs making 1 call to Foswiki::Prefs::Stack::newLevel |
369 | } | ||||
370 | |||||
371 | =begin TML | ||||
372 | |||||
373 | ---++ ObjectMethod loadSitePreferences() | ||||
374 | Add local site preferences to this preferences stack. | ||||
375 | |||||
376 | =cut | ||||
377 | |||||
378 | # spent 817µs (17+800) within Foswiki::Prefs::loadSitePreferences which was called:
# once (17µs+800µs) by Foswiki::new at line 2246 of /var/www/foswikidev/core/lib/Foswiki.pm | ||||
379 | 1 | 500ns | my $this = shift; | ||
380 | 1 | 4µs | if ( $Foswiki::cfg{LocalSitePreferences} ) { | ||
381 | 1 | 4µs | 1 | 13µs | my ( $web, $topic ) = # spent 13µs making 1 call to Foswiki::normalizeWebTopicName |
382 | $this->{session} | ||||
383 | ->normalizeWebTopicName( undef, $Foswiki::cfg{LocalSitePreferences} ); | ||||
384 | 1 | 2µs | 1 | 741µs | my $back = $this->_getBackend( $web, $topic ); # spent 741µs making 1 call to Foswiki::Prefs::_getBackend |
385 | 1 | 2µs | 1 | 47µs | $this->{main}->newLevel($back); # spent 47µs making 1 call to Foswiki::Prefs::Stack::newLevel |
386 | } | ||||
387 | } | ||||
388 | |||||
389 | =begin TML | ||||
390 | |||||
391 | ---++ ObjectMethod setSessionPreferences( %values ) | ||||
392 | |||||
393 | Set the preference values in the parameters in the SESSION stack. | ||||
394 | |||||
395 | =cut | ||||
396 | |||||
397 | # spent 324µs (120+204) within Foswiki::Prefs::setSessionPreferences which was called 9 times, avg 36µs/call:
# 8 times (95µs+158µs) by Foswiki::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Macros/INCLUDE.pm:339] at line 203 of /var/www/foswikidev/core/lib/Foswiki/Macros/INCLUDE.pm, avg 32µs/call
# once (25µs+45µs) by Foswiki::UI::View::view at line 407 of /var/www/foswikidev/core/lib/Foswiki/UI/View.pm | ||||
398 | 9 | 15µs | my ( $this, %values ) = @_; | ||
399 | 9 | 5µs | my $stack = $this->{main}; | ||
400 | 9 | 2µs | my $num = 0; | ||
401 | 9 | 24µs | while ( my ( $k, $v ) = each %values ) { | ||
402 | 10 | 15µs | 10 | 26µs | next if $stack->finalized($k); # spent 26µs making 10 calls to Foswiki::Prefs::Stack::finalized, avg 3µs/call |
403 | 10 | 16µs | 10 | 178µs | $num += $stack->insert( 'Set', $k, $v ); # spent 178µs making 10 calls to Foswiki::Prefs::Stack::insert, avg 18µs/call |
404 | } | ||||
405 | |||||
406 | 9 | 26µs | return $num; | ||
407 | } | ||||
408 | |||||
409 | =begin TML | ||||
410 | |||||
411 | ---++ ObjectMethod setInternalPreferences( %values ) | ||||
412 | |||||
413 | Designed specifically for imposing the value of preferences on a short-term | ||||
414 | basis in the code, internal preferences override all other definitions of | ||||
415 | the same tag. This function should be used with great care. | ||||
416 | |||||
417 | For those who are used to the old code, internal preferences replace the old | ||||
418 | SESSION_TAGS field from the Foswiki object. | ||||
419 | |||||
420 | =cut | ||||
421 | |||||
422 | # spent 3.30ms within Foswiki::Prefs::setInternalPreferences which was called 693 times, avg 5µs/call:
# 238 times (1.14ms+0s) by Foswiki::innerExpandMacros at line 3071 of /var/www/foswikidev/core/lib/Foswiki.pm, avg 5µs/call
# 238 times (1.09ms+0s) by Foswiki::innerExpandMacros at line 3098 of /var/www/foswikidev/core/lib/Foswiki.pm, avg 5µs/call
# 100 times (553µs+0s) by Foswiki::expandMacros at line 3615 of /var/www/foswikidev/core/lib/Foswiki.pm, avg 6µs/call
# 100 times (420µs+0s) by Foswiki::expandMacros at line 3632 of /var/www/foswikidev/core/lib/Foswiki.pm, avg 4µs/call
# 8 times (44µs+0s) by Foswiki::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Macros/INCLUDE.pm:339] at line 206 of /var/www/foswikidev/core/lib/Foswiki/Macros/INCLUDE.pm, avg 6µs/call
# 8 times (39µs+0s) by Foswiki::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Macros/INCLUDE.pm:356] at line 345 of /var/www/foswikidev/core/lib/Foswiki/Macros/INCLUDE.pm, avg 5µs/call
# once (14µs+0s) by Foswiki::new at line 2235 of /var/www/foswikidev/core/lib/Foswiki.pm | ||||
423 | 693 | 835µs | my ( $this, %values ) = @_; | ||
424 | |||||
425 | 693 | 3.18ms | while ( my ( $k, $v ) = each %values ) { | ||
426 | $this->{internals}{$k} = $v; | ||||
427 | } | ||||
428 | } | ||||
429 | |||||
430 | =begin TML | ||||
431 | |||||
432 | ---++ ObjectMethod getPreference( $key ) -> $value | ||||
433 | * =$key - key to look up | ||||
434 | |||||
435 | Returns the finalised preference value. | ||||
436 | |||||
437 | =cut | ||||
438 | |||||
439 | # spent 29.4ms (23.3+6.09) within Foswiki::Prefs::getPreference which was called 1405 times, avg 21µs/call:
# 537 times (18.8ms+3.60ms) by Foswiki::_expandMacroOnTopicRendering at line 3389 of /var/www/foswikidev/core/lib/Foswiki.pm, avg 42µs/call
# 238 times (502µs+70µs) by Foswiki::innerExpandMacros at line 3064 of /var/www/foswikidev/core/lib/Foswiki.pm, avg 2µs/call
# 238 times (443µs+55µs) by Foswiki::innerExpandMacros at line 3065 of /var/www/foswikidev/core/lib/Foswiki.pm, avg 2µs/call
# 100 times (211µs+0s) by Foswiki::expandMacros at line 3613 of /var/www/foswikidev/core/lib/Foswiki.pm, avg 2µs/call
# 100 times (155µs+0s) by Foswiki::expandMacros at line 3614 of /var/www/foswikidev/core/lib/Foswiki.pm, avg 2µs/call
# 50 times (1.30ms+894µs) by Foswiki::getSkin at line 1458 of /var/www/foswikidev/core/lib/Foswiki.pm, avg 44µs/call
# 49 times (618µs+406µs) by Foswiki::Func::getPreferencesValue at line 833 of /var/www/foswikidev/core/lib/Foswiki/Func.pm, avg 21µs/call
# 18 times (335µs+302µs) by Foswiki::Render::_renderExistingWikiWord at line 1355 of /var/www/foswikidev/core/lib/Foswiki/Render.pm, avg 35µs/call
# 13 times (166µs+114µs) by Foswiki::If::OP_defined::evaluate at line 46 of /var/www/foswikidev/core/lib/Foswiki/If/OP_defined.pm, avg 22µs/call
# 9 times (169µs+167µs) by Foswiki::INCLUDE at line 378 of /var/www/foswikidev/core/lib/Foswiki/Macros/INCLUDE.pm, avg 37µs/call
# 8 times (150µs+139µs) by Foswiki::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Macros/INCLUDE.pm:339] at line 294 of /var/www/foswikidev/core/lib/Foswiki/Macros/INCLUDE.pm, avg 36µs/call
# 8 times (18µs+0s) by Foswiki::_includeTopic at line 191 of /var/www/foswikidev/core/lib/Foswiki/Macros/INCLUDE.pm, avg 2µs/call
# 8 times (12µs+0s) by Foswiki::_includeTopic at line 192 of /var/www/foswikidev/core/lib/Foswiki/Macros/INCLUDE.pm, avg 2µs/call
# 7 times (71µs+39µs) by Foswiki::WIKINAME at line 19 of /var/www/foswikidev/core/lib/Foswiki/Macros/WIKINAME.pm, avg 16µs/call
# 6 times (111µs+101µs) by Foswiki::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Macros/INCLUDE.pm:339] at line 318 of /var/www/foswikidev/core/lib/Foswiki/Macros/INCLUDE.pm, avg 35µs/call
# 5 times (111µs+109µs) by Foswiki::Render::getRenderedVersion at line 528 of /var/www/foswikidev/core/lib/Foswiki/Render.pm, avg 44µs/call
# 2 times (32µs+23µs) by Foswiki::Func::getPluginPreferencesValue at line 857 of /var/www/foswikidev/core/lib/Foswiki/Func.pm, avg 27µs/call
# 2 times (22µs+12µs) by Foswiki::USERNAME at line 20 of /var/www/foswikidev/core/lib/Foswiki/Macros/USERNAME.pm, avg 17µs/call
# 2 times (23µs+12µs) by Foswiki::WIKIUSERNAME at line 19 of /var/www/foswikidev/core/lib/Foswiki/Macros/WIKIUSERNAME.pm, avg 17µs/call
# 2 times (5µs+0s) by Foswiki::LoginManager::_LOGOUTURL at line 1389 of /var/www/foswikidev/core/lib/Foswiki/LoginManager.pm, avg 2µs/call
# once (21µs+20µs) by Foswiki::_lookupIcon at line 31 of /var/www/foswikidev/core/lib/Foswiki/Macros/ICON.pm
# once (21µs+13µs) by Foswiki::Plugins::enable at line 288 of /var/www/foswikidev/core/lib/Foswiki/Plugins.pm
# once (13µs+8µs) by Foswiki::UI::View::view at line 281 of /var/www/foswikidev/core/lib/Foswiki/UI/View.pm | ||||
440 | 1405 | 588µs | my ( $this, $key ) = @_; | ||
441 | 1405 | 2.25ms | if ( defined $this->{internals}{$key} ) { | ||
442 | return $this->{internals}{$key}; | ||||
443 | } | ||||
444 | |||||
445 | 673 | 73µs | my $value; | ||
446 | 673 | 315µs | my $stack = $this->{main}; | ||
447 | 673 | 922µs | 673 | 1.09ms | my $prevLev = $stack->backAtLevel(-2); # spent 1.09ms making 673 calls to Foswiki::Prefs::Stack::backAtLevel, avg 2µs/call |
448 | 673 | 1.55ms | 1038 | 2.79ms | if ( $prevLev && !$stack->finalizedBefore( $key, -2 ) ) { # spent 2.02ms making 673 calls to Foswiki::Prefs::Stack::finalizedBefore, avg 3µs/call
# spent 779µs making 365 calls to Foswiki::Prefs::TopicRAM::getLocal, avg 2µs/call |
449 | $value = $prevLev->getLocal($key); | ||||
450 | } | ||||
451 | 673 | 944µs | 673 | 1.07ms | if ( !defined $value && $stack->prefIsDefined($key) ) { # spent 1.07ms making 673 calls to Foswiki::Prefs::Stack::prefIsDefined, avg 2µs/call |
452 | 101 | 127µs | 101 | 788µs | my $defLevel = $stack->getDefinitionLevel($key); # spent 788µs making 101 calls to Foswiki::Prefs::Stack::getDefinitionLevel, avg 8µs/call |
453 | 101 | 51µs | my $prefix = $this->{prefix}->[$defLevel]; | ||
454 | 101 | 41µs | $key =~ s/^\Q$prefix\E// if $prefix; | ||
455 | 101 | 245µs | 202 | 347µs | $value = $stack->backAtLevel($defLevel)->get($key); # spent 221µs making 99 calls to Foswiki::Prefs::TopicRAM::get, avg 2µs/call
# spent 117µs making 101 calls to Foswiki::Prefs::Stack::backAtLevel, avg 1µs/call
# spent 8µs making 2 calls to Foswiki::Prefs::HASH::get, avg 4µs/call |
456 | } | ||||
457 | 673 | 1.40ms | return $value; | ||
458 | } | ||||
459 | |||||
460 | =begin TML | ||||
461 | |||||
462 | ---++ ObjectMethod stringify([$key]) -> $text | ||||
463 | |||||
464 | Generate TML-formatted information about the key (all keys if $key is undef) | ||||
465 | |||||
466 | =cut | ||||
467 | |||||
468 | sub stringify { | ||||
469 | my ( $this, $key ) = @_; | ||||
470 | |||||
471 | my $stack = $this->{main}; | ||||
472 | my @keys = defined $key ? ($key) : sort $stack->prefs; | ||||
473 | my @list; | ||||
474 | foreach my $k (@keys) { | ||||
475 | my $val = Foswiki::entityEncode( $this->getPreference($k) || '' ); | ||||
476 | push( @list, ' * Set ' . "$k = \"$val\"" ); | ||||
477 | next unless exists $stack->{'map'}{$k}; | ||||
478 | my $defLevel = $stack->getDefinitionLevel($k); | ||||
479 | if ( $stack->backAtLevel($defLevel)->can('topicObject') ) { | ||||
480 | my $topicObject = $stack->backAtLevel($defLevel)->topicObject(); | ||||
481 | push( @list, | ||||
482 | " * $k was " | ||||
483 | . ( $stack->finalized($k) ? '*finalised*' : 'defined' ) | ||||
484 | . ' in <nop>' | ||||
485 | . $topicObject->web() . '.' | ||||
486 | . $topicObject->topic() ); | ||||
487 | } | ||||
488 | } | ||||
489 | |||||
490 | @keys = | ||||
491 | defined $key ? ($key) : ( sort $stack->backAtLevel(-2)->localPrefs ); | ||||
492 | foreach my $k (@keys) { | ||||
493 | next | ||||
494 | unless defined $stack->backAtLevel(-2)->getLocal($k) | ||||
495 | && !$stack->finalizedBefore( $k, -2 ); | ||||
496 | my $val = | ||||
497 | Foswiki::entityEncode( $stack->backAtLevel(-2)->getLocal($k) ); | ||||
498 | push( @list, ' * Local ' . "$k = \"$val\"" ); | ||||
499 | } | ||||
500 | |||||
501 | return join( "\n", @list ) . "\n"; | ||||
502 | } | ||||
503 | |||||
504 | 1 | 2µs | 1; | ||
505 | __END__ |