Filename | /var/www/foswiki11/lib/Foswiki/Plugins/SetFormValuesPlugin.pm |
Statements | Executed 18 statements in 683µs |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 20µs | 32µs | BEGIN@68 | Foswiki::Plugins::SetFormValuesPlugin::
1 | 1 | 1 | 16µs | 26µs | initPlugin | Foswiki::Plugins::SetFormValuesPlugin::
1 | 1 | 1 | 10µs | 16µs | BEGIN@69 | Foswiki::Plugins::SetFormValuesPlugin::
1 | 1 | 1 | 6µs | 6µs | BEGIN@73 | Foswiki::Plugins::SetFormValuesPlugin::
1 | 1 | 1 | 4µs | 4µs | BEGIN@71 | Foswiki::Plugins::SetFormValuesPlugin::
1 | 1 | 1 | 3µs | 3µs | BEGIN@72 | Foswiki::Plugins::SetFormValuesPlugin::
0 | 0 | 0 | 0s | 0s | beforeSaveHandler | Foswiki::Plugins::SetFormValuesPlugin::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # See bottom of file for default license and copyright information | ||||
2 | |||||
3 | =begin TML | ||||
4 | |||||
5 | ---+ package Foswiki::Plugins::SetFormValuesPlugin | ||||
6 | |||||
7 | Foswiki plugins 'listen' to events happening in the core by registering an | ||||
8 | interest in those events. They do this by declaring 'plugin handlers'. These | ||||
9 | are simply functions with a particular name that, if they exist in your | ||||
10 | plugin, will be called by the core. | ||||
11 | |||||
12 | This is an empty Foswiki plugin. It is a fully defined plugin, but is | ||||
13 | disabled by default in a Foswiki installation. Use it as a template | ||||
14 | for your own plugins. | ||||
15 | |||||
16 | To interact with Foswiki use ONLY the official APIs | ||||
17 | documented in %SYSTEMWEB%.DevelopingPlugins. <strong>Do not reference any | ||||
18 | packages, functions or variables elsewhere in Foswiki</strong>, as these are | ||||
19 | subject to change without prior warning, and your plugin may suddenly stop | ||||
20 | working. | ||||
21 | |||||
22 | Error messages can be output using the =Foswiki::Func= =writeWarning= and | ||||
23 | =writeDebug= functions. These logs can be found in the Foswiki/working/logs | ||||
24 | directory. You can also =print STDERR=; the output will appear in the | ||||
25 | webserver error log. The {WarningsAreErrors} configure setting makes | ||||
26 | Foswiki less tolerant of errors, and it is recommended to set it during | ||||
27 | development. It can be set using configure, in the 'Miscellaneous' | ||||
28 | section. Most handlers can also throw exceptions (e.g. | ||||
29 | [[%SCRIPTURL{view}%/%SYSTEMWEB%/PerlDoc?module=Foswiki::OopsException][Foswiki::OopsException]]) | ||||
30 | |||||
31 | For increased performance, all handler functions except =initPlugin= are | ||||
32 | commented out below. *To enable a handler* remove the leading =#= from | ||||
33 | each line of the function. For efficiency and clarity, you should | ||||
34 | only uncomment handlers you actually use. | ||||
35 | |||||
36 | __NOTE:__ When developing a plugin it is important to remember that | ||||
37 | Foswiki is tolerant of plugins that do not compile. In this case, | ||||
38 | the failure will be silent but the plugin will not be available. | ||||
39 | See %SYSTEMWEB%.InstalledPlugins for error messages. | ||||
40 | |||||
41 | __NOTE:__ Foswiki:Development.StepByStepRenderingOrder helps you decide which | ||||
42 | rendering handler to use. When writing handlers, keep in mind that these may | ||||
43 | be invoked on included topics. For example, if a plugin generates links to the | ||||
44 | current topic, these need to be generated before the =afterCommonTagsHandler= | ||||
45 | is run. After that point in the rendering loop we have lost the information | ||||
46 | that the text had been included from another topic. | ||||
47 | |||||
48 | __NOTE:__ Not all handlers (and not all parameters passed to handlers) are | ||||
49 | available with all versions of Foswiki. Where a handler has been added | ||||
50 | the POD comment will indicate this with a "Since" line | ||||
51 | e.g. *Since:* Foswiki::Plugins::VERSION 1.1 | ||||
52 | |||||
53 | Deprecated handlers are still available, and can continue to be used to | ||||
54 | maintain compatibility with earlier releases, but will be removed at some | ||||
55 | point in the future. If you do implement deprecated handlers, then you can | ||||
56 | do no harm by simply keeping them in your code, but you are recommended to | ||||
57 | implement the alternative as soon as possible. | ||||
58 | |||||
59 | See http://foswiki.org/Download/ReleaseDates for a breakdown of release | ||||
60 | versions. | ||||
61 | |||||
62 | =cut | ||||
63 | |||||
64 | # change the package name!!! | ||||
65 | package Foswiki::Plugins::SetFormValuesPlugin; | ||||
66 | |||||
67 | # Always use strict to enforce variable scoping | ||||
68 | 2 | 30µs | 2 | 45µs | # spent 32µs (20+13) within Foswiki::Plugins::SetFormValuesPlugin::BEGIN@68 which was called:
# once (20µs+13µs) by Foswiki::Plugin::BEGIN@2.30 at line 68 # spent 32µs making 1 call to Foswiki::Plugins::SetFormValuesPlugin::BEGIN@68
# spent 13µs making 1 call to strict::import |
69 | 2 | 25µs | 2 | 21µs | # spent 16µs (10+6) within Foswiki::Plugins::SetFormValuesPlugin::BEGIN@69 which was called:
# once (10µs+6µs) by Foswiki::Plugin::BEGIN@2.30 at line 69 # spent 16µs making 1 call to Foswiki::Plugins::SetFormValuesPlugin::BEGIN@69
# spent 6µs making 1 call to warnings::import |
70 | |||||
71 | 2 | 19µs | 1 | 4µs | # spent 4µs within Foswiki::Plugins::SetFormValuesPlugin::BEGIN@71 which was called:
# once (4µs+0s) by Foswiki::Plugin::BEGIN@2.30 at line 71 # spent 4µs making 1 call to Foswiki::Plugins::SetFormValuesPlugin::BEGIN@71 |
72 | 2 | 21µs | 1 | 3µs | # spent 3µs within Foswiki::Plugins::SetFormValuesPlugin::BEGIN@72 which was called:
# once (3µs+0s) by Foswiki::Plugin::BEGIN@2.30 at line 72 # spent 3µs making 1 call to Foswiki::Plugins::SetFormValuesPlugin::BEGIN@72 |
73 | 2 | 559µs | 1 | 6µs | # spent 6µs within Foswiki::Plugins::SetFormValuesPlugin::BEGIN@73 which was called:
# once (6µs+0s) by Foswiki::Plugin::BEGIN@2.30 at line 73 # spent 6µs making 1 call to Foswiki::Plugins::SetFormValuesPlugin::BEGIN@73 |
74 | |||||
75 | # $VERSION is referred to by Foswiki, and is the only global variable that | ||||
76 | # *must* exist in this package. Two version formats are supported: | ||||
77 | # | ||||
78 | # Recommended: Dotted triplet. Use "v1.2.3" format for releases, and | ||||
79 | # "v1.2.3_001" for "alpha" versions. The v prefix is required. | ||||
80 | # This format uses the "declare" format | ||||
81 | # use version; our $VERSION = version->declare("v1.2.0"); | ||||
82 | # | ||||
83 | # Alternative: Simple decimal version. Use "1.2" format for releases, and | ||||
84 | # "1.2_001" for "alpha" versions. Do NOT use the "v" prefix. This style | ||||
85 | # is set either by using the "parse" method, or by a simple assignment. | ||||
86 | # use version; our $VERSION = version->parse("1.20_001"); OR | ||||
87 | # our $VERSION = "1.20_001"; # version->parse isn't really needed | ||||
88 | # | ||||
89 | # To convert from a decimal version to a dotted version, first normalize the | ||||
90 | # decimal version, then increment it. | ||||
91 | # perl -Mversion -e 'print version->parse("4.44")->normal' ==> v4.440.0 | ||||
92 | # In this example the next version would be v4.441.0. | ||||
93 | # | ||||
94 | # Note: Alpha versions compare as numerically lower than the non-alpha version | ||||
95 | # so the versions in ascending order are: | ||||
96 | # v1.2.1_001 -> v1.2.1 -> v1.2.2_001 -> v1.2.2 | ||||
97 | # | ||||
98 | # These statements MUST be on the same line. See "perldoc version" for more | ||||
99 | # information on version strings. | ||||
100 | 1 | 600ns | our $VERSION = '1.0'; | ||
101 | |||||
102 | # $RELEASE is used in the "Find More Extensions" automation in configure. | ||||
103 | # It is a manually maintained string used to identify functionality steps. | ||||
104 | # You can use any of the following formats: | ||||
105 | # tuple - a sequence of integers separated by . e.g. 1.2.3. The numbers | ||||
106 | # usually refer to major.minor.patch release or similar. You can | ||||
107 | # use as many numbers as you like e.g. '1' or '1.2.3.4.5'. | ||||
108 | # isodate - a date in ISO8601 format e.g. 2009-08-07 | ||||
109 | # date - a date in 1 Jun 2009 format. Three letter English month names only. | ||||
110 | # Note: it's important that this string is exactly the same in the extension | ||||
111 | # topic - if you use %$RELEASE% with BuildContrib this is done automatically. | ||||
112 | # It is preferred to keep this compatible with $VERSION. At some future | ||||
113 | # date, Foswiki will deprecate RELEASE and use the VERSION string. | ||||
114 | 1 | 100ns | our $RELEASE = '1.1'; | ||
115 | |||||
116 | # Short description of this plugin | ||||
117 | # One line description, is shown in the %SYSTEMWEB%.TextFormattingRules topic: | ||||
118 | 1 | 300ns | our $SHORTDESCRIPTION = 'Set values in topic form fields based on changes of other form fields'; | ||
119 | |||||
120 | # You must set $NO_PREFS_IN_TOPIC to 0 if you want your plugin to use | ||||
121 | # preferences set in the plugin topic. This is required for compatibility | ||||
122 | # with older plugins, but imposes a significant performance penalty, and | ||||
123 | # is not recommended. Instead, leave $NO_PREFS_IN_TOPIC at 1 and use | ||||
124 | # =$Foswiki::cfg= entries, or if you want the users | ||||
125 | # to be able to change settings, then use standard Foswiki preferences that | ||||
126 | # can be defined in your %USERSWEB%.SitePreferences and overridden at the web | ||||
127 | # and topic level. | ||||
128 | # | ||||
129 | # %SYSTEMWEB%.DevelopingPlugins has details of how to define =$Foswiki::cfg= | ||||
130 | # entries so they can be used with =configure=. | ||||
131 | 1 | 100ns | our $NO_PREFS_IN_TOPIC = 1; | ||
132 | |||||
133 | =begin TML | ||||
134 | |||||
135 | ---++ initPlugin($topic, $web, $user) -> $boolean | ||||
136 | * =$topic= - the name of the topic in the current CGI query | ||||
137 | * =$web= - the name of the web in the current CGI query | ||||
138 | * =$user= - the login name of the user | ||||
139 | * =$installWeb= - the name of the web the plugin topic is in | ||||
140 | (usually the same as =$Foswiki::cfg{SystemWebName}=) | ||||
141 | |||||
142 | *REQUIRED* | ||||
143 | |||||
144 | Called to initialise the plugin. If everything is OK, should return | ||||
145 | a non-zero value. On non-fatal failure, should write a message | ||||
146 | using =Foswiki::Func::writeWarning= and return 0. In this case | ||||
147 | %<nop>FAILEDPLUGINS% will indicate which plugins failed. | ||||
148 | |||||
149 | In the case of a catastrophic failure that will prevent the whole | ||||
150 | installation from working safely, this handler may use 'die', which | ||||
151 | will be trapped and reported in the browser. | ||||
152 | |||||
153 | __Note:__ Please align macro names with the Plugin name, e.g. if | ||||
154 | your Plugin is called !FooBarPlugin, name macros FOOBAR and/or | ||||
155 | FOOBARSOMETHING. This avoids namespace issues. | ||||
156 | |||||
157 | =cut | ||||
158 | |||||
159 | # spent 26µs (16+10) within Foswiki::Plugins::SetFormValuesPlugin::initPlugin which was called:
# once (16µs+10µs) by Foswiki::Plugin::__ANON__[/var/www/foswiki11/lib/Foswiki/Plugin.pm:241] at line 234 of /var/www/foswiki11/lib/Foswiki/Plugin.pm | ||||
160 | 1 | 2µs | my ( $topic, $web, $user, $installWeb ) = @_; | ||
161 | |||||
162 | # check for Plugins.pm versions | ||||
163 | 1 | 17µs | 1 | 10µs | if ( $Foswiki::Plugins::VERSION < 2.0 ) { # spent 10µs making 1 call to version::vxs::VCMP |
164 | Foswiki::Func::writeWarning( 'Version mismatch between ', | ||||
165 | __PACKAGE__, ' and Plugins.pm' ); | ||||
166 | return 0; | ||||
167 | } | ||||
168 | |||||
169 | # Example code of how to get a preference value, register a macro | ||||
170 | # handler and register a RESTHandler (remove code you do not need) | ||||
171 | |||||
172 | # Set your per-installation plugin configuration in LocalSite.cfg, | ||||
173 | # like this: | ||||
174 | # $Foswiki::cfg{Plugins}{EmptyPlugin}{ExampleSetting} = 1; | ||||
175 | # See %SYSTEMWEB%.DevelopingPlugins#ConfigSpec for information | ||||
176 | # on integrating your plugin configuration with =configure=. | ||||
177 | |||||
178 | # Always provide a default in case the setting is not defined in | ||||
179 | # LocalSite.cfg. | ||||
180 | # my $setting = $Foswiki::cfg{Plugins}{EmptyPlugin}{ExampleSetting} || 0; | ||||
181 | |||||
182 | # Register the _EXAMPLETAG function to handle %EXAMPLETAG{...}% | ||||
183 | # This will be called whenever %EXAMPLETAG% or %EXAMPLETAG{...}% is | ||||
184 | # seen in the topic text. | ||||
185 | # Foswiki::Func::registerTagHandler( 'EXAMPLETAG', \&_EXAMPLETAG ); | ||||
186 | |||||
187 | # Allow a sub to be called from the REST interface | ||||
188 | # using the provided alias | ||||
189 | # Foswiki::Func::registerRESTHandler( 'example', \&restExample ); | ||||
190 | |||||
191 | # Plugin correctly initialized | ||||
192 | 1 | 6µs | return 1; | ||
193 | } | ||||
194 | |||||
195 | # The function used to handle the %EXAMPLETAG{...}% macro | ||||
196 | # You would have one of these for each macro you want to process. | ||||
197 | #sub _EXAMPLETAG { | ||||
198 | # my($session, $params, $topic, $web, $topicObject) = @_; | ||||
199 | # # $session - a reference to the Foswiki session object | ||||
200 | # # (you probably won't need it, but documented in Foswiki.pm) | ||||
201 | # # $params= - a reference to a Foswiki::Attrs object containing | ||||
202 | # # parameters. | ||||
203 | # # This can be used as a simple hash that maps parameter names | ||||
204 | # # to values, with _DEFAULT being the name for the default | ||||
205 | # # (unnamed) parameter. | ||||
206 | # # $topic - name of the topic in the query | ||||
207 | # # $web - name of the web in the query | ||||
208 | # # $topicObject - a reference to a Foswiki::Meta object containing the | ||||
209 | # # topic the macro is being rendered in (new for foswiki 1.1.x) | ||||
210 | # # Return: the result of processing the macro. This will replace the | ||||
211 | # # macro call in the final text. | ||||
212 | # | ||||
213 | # # For example, %EXAMPLETAG{'hamburger' sideorder="onions"}% | ||||
214 | # # $params->{_DEFAULT} will be 'hamburger' | ||||
215 | # # $params->{sideorder} will be 'onions' | ||||
216 | #} | ||||
217 | |||||
218 | =begin TML | ||||
219 | |||||
220 | ---++ beforeSaveHandler($text, $topic, $web, $meta ) | ||||
221 | * =$text= - text _with embedded meta-data tags_ | ||||
222 | * =$topic= - the name of the topic in the current CGI query | ||||
223 | * =$web= - the name of the web in the current CGI query | ||||
224 | * =$meta= - the metadata of the topic being saved, represented by a Foswiki::Meta object. | ||||
225 | |||||
226 | This handler is called each time a topic is saved. | ||||
227 | |||||
228 | *NOTE:* meta-data is embedded in =$text= (using %META: tags). If you modify | ||||
229 | the =$meta= object, then it will override any changes to the meta-data | ||||
230 | embedded in the text. Modify *either* the META in the text *or* the =$meta= | ||||
231 | object, never both. You are recommended to modify the =$meta= object rather | ||||
232 | than the text, as this approach is proof against changes in the embedded | ||||
233 | text format. | ||||
234 | |||||
235 | *Since:* Foswiki::Plugins::VERSION = 2.0 | ||||
236 | |||||
237 | =cut | ||||
238 | |||||
239 | sub beforeSaveHandler { | ||||
240 | my ( $text, $topic, $web, $meta ) = @_; | ||||
241 | |||||
242 | # You can work on $text in place by using the special perl | ||||
243 | # variable $_[0]. These allow you to operate on $text | ||||
244 | # as if it was passed by reference; for example: | ||||
245 | |||||
246 | my $rulesTopic; | ||||
247 | |||||
248 | return 1 unless ( $rulesTopic = Foswiki::Func::getPreferencesValue('SETFORMVALUESPLUGIN_RULES') ); | ||||
249 | $rulesTopic =~ s/\s+$//; | ||||
250 | |||||
251 | my ( $matchForm, $matchField, $matchValue, $targetField, $targetValue, $targetRule ); | ||||
252 | |||||
253 | my $rulesWeb = $web; | ||||
254 | if ( $rulesTopic =~ /(.+)\.(.+)/ ) { | ||||
255 | $rulesWeb = $1; | ||||
256 | $rulesTopic = $2; | ||||
257 | } | ||||
258 | |||||
259 | foreach ( | ||||
260 | split( /\n/, Foswiki::Func::readTopicText( $rulesWeb, $rulesTopic, undef, 1 ) ) ) { | ||||
261 | |||||
262 | # form, match field, match value, target field, target value, condition (optional for backwards compatibility) | ||||
263 | if ( m/\|\s*([^\s|*]+)\s*\|\s*([^\|]+?)\s*\|\s*([^\|]*?)\s*\|\s*([^\|]+?)\s*\|\s*([^\|]*?)\s*\|(?:\s*([^\|]*?)\s*\|)\s*$/ ) { | ||||
264 | ( $matchForm, $matchField, $matchValue, $targetField, $targetValue, $targetRule ) = ($1, $2, $3, $4, $5, $6 ); | ||||
265 | } else { | ||||
266 | next; | ||||
267 | } | ||||
268 | |||||
269 | # Form names, and fields names can never be 0 or empty. Values can and much be able to match. | ||||
270 | next unless ( $matchForm && $matchField && $targetField ); | ||||
271 | |||||
272 | if ( $meta->getFormName eq $matchForm ) { | ||||
273 | |||||
274 | my ( $oldmeta, $oldtext ) = Foswiki::Func::readTopic( $web, $topic ); | ||||
275 | |||||
276 | my $oldfieldhashref = $oldmeta->get( 'FIELD', $matchField ); | ||||
277 | next unless $oldfieldhashref; | ||||
278 | |||||
279 | my $oldValue = $oldfieldhashref ? | ||||
280 | $oldmeta->get( 'FIELD', $matchField )->{'value'} : | ||||
281 | ''; | ||||
282 | |||||
283 | my $newfieldhashref = $meta->get( 'FIELD', $matchField ); | ||||
284 | next unless $newfieldhashref; | ||||
285 | |||||
286 | my $newValue = $newfieldhashref ? | ||||
287 | $meta->get( 'FIELD', $matchField )->{'value'} : | ||||
288 | ''; | ||||
289 | |||||
290 | my $oldTargetFieldhashref = $oldmeta->get( 'FIELD', $targetField ); | ||||
291 | my $oldTargetValue = $oldTargetFieldhashref ? | ||||
292 | $oldmeta->get( 'FIELD', $targetField )->{'value'} : | ||||
293 | ''; | ||||
294 | |||||
295 | next if ( $targetRule eq 'EMPTY' && $oldTargetValue ne '' ); | ||||
296 | |||||
297 | my $currentDate = Foswiki::Time::formatTime( time(), $Foswiki::cfg{DefaultDateFormat} ); | ||||
298 | my $currentTime = Foswiki::Time::formatTime( time(), '$hour:$min'); | ||||
299 | $targetValue =~ s/\$date/$currentDate/; | ||||
300 | $targetValue =~ s/\$time/$currentTime/; | ||||
301 | |||||
302 | if ( $newValue ne $oldValue ) { | ||||
303 | $meta->putKeyed( 'FIELD', { name => $targetField, value => $targetValue } ) if ( $newValue =~ m/$matchValue/ ); | ||||
304 | } | ||||
305 | } | ||||
306 | } | ||||
307 | |||||
308 | return 1; | ||||
309 | } | ||||
310 | |||||
311 | 1 | 3µs | 1; | ||
312 | |||||
313 | __END__ |