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