Wiki source code of InvitationCommon

Last modified by Ecaterina Valica on 2019/03/27 14:32

Show last authors
1 {{velocity}}
2 #*
3 * Invitation Application
4 * This document contains common macros used by all documents in the Invitation Application.
5 *
6 * Macros in this script don't rely on any variables except those which are passed to them and the following:
7 *
8 * $doc the com.xpn.xwiki.api.Document object representing the document containing this code.
9 * $msg the internationalization message provider containing a get(String) and a get(String, List) function
10 * $xcontext the com.xpn.xwiki.Context object for this request
11 * $xwiki an object of the com.xpn.xwiki.api.XWiki class.
12 * $escapetool an object of class org.apache.velocity.tools.generic.EscapeTool
13 * $util used to get a newline character ($util.getNewLine())
14 *
15 * No macros in this script depend on any other macros.
16 *###
17 ##
18 #if($request.getParameter('test') == '1')
19 {{info}}testLoadInvitationConfig{{/info}}
20 #testLoadInvitationConfig()
21 #elseif($doc.documentReference.name == 'InvitationCommon')
22 {{info}}$services.localization.render('xe.invitation.internalDocument', ["${doc.getSpace()}.WebHome"]){{/info}}
23 #end
24 ##
25 #*
26 * Display a message for the sender (preview) or for the admin (review sent messages)
27 *
28 * $mail (XObject representing email message) the message to view
29 *
30 * $recipients (List<String>) (Optional) the list of email addresses to override the list provided by $mail
31 * used for preview because createMailFromTemplate will exclude addresses
32 * which are invalid and we want to show the invalid addresses to the
33 * user to tell them that they need to correct them.
34 *
35 * $invalidAddresses (List<String>) (Optional) List of invalid email addresses in recipients. Needed if you want to
36 * show the user that they made a mistake on some addresses.
37 * For each email in $invalidEmails, if it is also in $recipients, then it
38 * will be marked but left in the same order, emails in $invlaidEmails but
39 * not found in $recipients will end up at the end of the list.
40 *###
41 #macro(displayMessage, $mail, $recipients, $invalidAddresses)
42
43 {{html wiki=false clean=false}}
44 <div id="invitation-displaymessage" class="invitation">
45 <strong>$services.localization.render('xe.invitation.previewLabel')</strong>
46 <div class="invitation invitation-preview">
47 #set($recips = [])
48 #set($invalid = [])
49 ## get the lists of valid and invalid email addresses.
50 #if("$!invalidAddresses" == '')
51 #set($invalid = [])
52 #if("$!recipients" == '')
53 #set($recips = [$mail.getProperty('recipient').getValue().trim()])
54 #else
55 #set($discard = $recips.addAll($recipients))
56 #end
57 #else
58 ## Set to local variables to prevent altering input values.
59 #set($discard = $recips.addAll($recipients))
60 #set($discard = $invalid.addAll($invalidAddresses))
61 #end
62 ## Print the email addresses to be sent to.
63 ## To:
64 <strong>$services.localization.render('xe.invitation.toLabel')</strong>
65 <div id="preview-to-field" class="invitation-preview field">
66 #foreach($recip in $recips)
67 #if($invalid.contains($recip))
68 <span class="invalid-address">$!escapetool.xml($!recip)</span> ##
69 #set($discard = $invalid.remove($recip))
70 #else
71 <span class="valid-address">$!escapetool.xml($!recip)</span> ##
72 #end
73 #end
74 #foreach($recip in $invalid)
75 <span class="invalid-address">$!escapetool.xml($!recip)</span> ##
76 #end
77 &nbsp; ## used to make the field the correct size if it's empty.
78 </div>
79 ## Tell the user that some of the email addresses are invalid.
80 #if($invalidAddresses && $invalidAddresses.size() > 0)
81 <p class="invalid-address-message">
82 <span class="errormessage">
83 #if($recips.size() == 1)
84 ## The email address given is invalid and will not be sent to.
85 $services.localization.render('xe.invitation.displayMessage.theAddressIsInvalid')
86 #else
87 #if($invalid.size() > 1)
88 $services.localization.render('xe.invitation.displayMessage.someAddressesAreInvalid', [$invalidAddresses.size()])
89 #else
90 $services.localization.render('xe.invitation.displayMessage.anAddressesIsInvalid')
91 #end
92 #end
93 </span>
94 </p>
95 #end
96 ## Subject:
97 <strong>$services.localization.render('xe.invitation.subjectLabel')</strong>
98 <div id="preview-subjectline-field" class="invitation-preview field">
99 $escapetool.xml($mail.getProperty('subjectLine').getValue())
100 </div>
101 ## Message:
102 <strong>$services.localization.render('xe.invitation.contentLabel')</strong>
103 <div id="preview-messagebody-field" class="invitation-preview field">
104 $mail.getProperty('messageBody').getValue()
105 </div>
106 </div>
107 </div>
108 {{/html}}
109
110 #end
111 ##
112 #*
113 * Load the configuration.
114 * Only works if the script calling this macro has permission to view InvitationConfig
115 * (or create it if it doesn't exist)
116 *
117 * $config (Map<String, String>) will be populated with invitation configuration.
118 *
119 * $configDocName (String) (Optional) will load configuration from this document, if not specified will use
120 * 'InvitationConfig' in the same space as $doc.
121 *
122 * $configClassName (String) (Optional) will load configuration from object of this class, if not specified will use
123 * 'Invitation' in the same space as $doc.
124 *###
125 #macro(loadInvitationConfig, $config, $configDocName, $configClassName)
126 #define($discard)
127 #if("$!configDocName" == '')
128 #set($configDocNameInternal = "${doc.getSpace()}.InvitationConfig")
129 #else
130 #set($configDocNameInternal = $configDocName)
131 #end
132 #if("$!configClassName" == '')
133 #set($configClassNameInternal = "${doc.getSpace()}.WebHome")
134 #else
135 #set($configClassNameInternal = $configClassName)
136 #end
137 ##
138 ## Load some parameters from the configuration.
139 #set($configDoc = $xwiki.getDocumentAsAuthor($configDocNameInternal))
140 ##
141 ## If no configuration document exists, create one and save it.
142 #if($configDoc.isNew())
143 ##
144 ## load the default configuration from this document.
145 #set($thisDocument = $xwiki.getDocumentAsAuthor("${doc.getSpace()}.InvitationCommon"))
146 #set($defaultConfigObj = $thisDocument.getObject($configClassNameInternal))
147 #foreach($element in $defaultConfigObj.getProperties())
148 $config.put($element.getName(), $defaultConfigObj.getProperty($element.getName()).getValue())
149 #end
150 ##
151 #set($configDocContent = '{{velo' + 'city}}{{info}}$services.localization.render(''xe.invitation.internalDocument'', ["'
152 + "$!config.get('mainPage')" + '"]){{/info}}{{/velo' + 'city}}')
153 $configDoc.setContent($configDocContent)
154 $configDoc.setParent($configClassNameInternal)
155 #set($configObj = $configDoc.newObject($configClassNameInternal))
156 #foreach($key in $config.keySet())
157 $configObj.set($key, $config.get($key))
158 #end
159 ## Now create the configurable objects.
160 #set($cfgable = $configDoc.newObject('XWiki.ConfigurableClass'))
161 $cfgable.set('displayInSection', 'Invitation')
162 $cfgable.set('configurationClass', $configClassNameInternal)
163 $cfgable.set('configureGlobally', 1)
164 #set($propsToShow = 'subjectLineTemplate|messageBodyTemplate|emailRegex|from_address|allowUsersOfOtherWikis'
165 + '|usersMayPersonalizeMessage|usersMaySendToMultiple|emailClass|emailContainer')
166 $cfgable.set('propertiesToShow', $propsToShow)
167 #set($cfgable = $configDoc.newObject('XWiki.ConfigurableClass'))
168 $cfgable.set('displayInSection', 'Invitation')
169 $cfgable.set('heading', '$services.localization.render(''xe.invitation.configuration.smtpHeading'')')
170 $cfgable.set('configurationClass', $configClassNameInternal)
171 $cfgable.set('configureGlobally', 1)
172 $cfgable.set('propertiesToShow',
173 'smtp_server_password|smtp_server_username|smtp_port|smtp_server|javamail_extra_props')
174 $configDoc.saveAsAuthor()
175 #else
176 ## load the configuration object...
177 #set($configObj = $configDoc.getObject($configClassNameInternal))
178 #foreach($element in $configObj.getProperties())
179 $config.put($element.getName(), $configObj.getProperty($element.getName()).getValue())
180 #end
181 #end
182 #end## define $discard
183 ## Now invoke the defined code...
184 #set($discard = $discard.toString())
185 #end
186 ##
187 #*
188 * Basic unit testing of the macro above.
189 *###
190 #macro(testLoadInvitationConfig)
191 #set($configDoc = $xwiki.getDocumentAsAuthor("${doc.getSpace()}.InvitationConfig"))
192 #if(!$configDoc.isNew())
193 $configDoc.deleteAsAuthor()
194 #end
195 #set($configClass = $xwiki.getDocumentAsAuthor("${doc.getSpace()}.WebHome"))
196 #if($configClass.isNew())
197 {{error}}Class document [[${doc.getSpace()}.WebHome]] not found. can't run test.{{/error}}
198 #else
199 #set($config = {})
200 #loadInvitationConfig($config, 'HopefullyNonexistantSpace')
201 #if($config.size() < 9)
202 {{error}}Config map too small{{/error}}
203 #end
204 #if($config.get('from_address') != 'no-reply@localhost.localdomain')
205 {{error}}form_address incorrect, expecting "no-reply@localhost.localdomain" got "$config.get('from_address')"{{/error}}
206 #end
207 #set($configDoc = $xwiki.getDocumentAsAuthor("${doc.getSpace()}.InvitationConfig"))
208 #if($configDoc.isNew())
209 {{error}}Config document not created{{/error}}
210 #else
211 #set($configObj = $configDoc.getObject("${doc.getSpace()}.Invitation"))
212 $configObj.set('from_address', 'thisisatest@localhost.localdomain')
213 $configDoc.saveAsAuthor()
214 $config.clear()
215 #loadInvitationConfig($config, 'HopefullyNonexistantSpace')
216 #if($config.get('from_address') != 'thisisatest@localhost.localdomain')
217 {{error}}altering config parameter failed.{{/error}}
218 #end
219 #end
220 #end
221 #set($configDoc = $xwiki.getDocumentAsAuthor("${doc.getSpace()}.InvitationConfig"))
222 #if(!$configDoc.isNew())
223 $configDoc.deleteAsAuthor()
224 #end
225 #end
226 ##
227 #**
228 * Load mail from mail containing document.
229 *
230 * $config (Map<String, String>) will be used to get the name of the email class.
231 *
232 * $emailContainer (Document) the document to get the email from.
233 *
234 * $mail (Map<String, XObject>) will be populated with email message XObjects by their messageID.
235 *###
236 #macro(loadInvitationMail, $config, $emailContainer, $mail)
237 ## If this doesn't already exist, it's created.
238 #if($emailContainer.isNew())
239 #set($emailContainerContent = '{{velo' + 'city}}{{info}}$services.localization.render(''xe.invitation.internalDocument'', ["'
240 + "$config.get('emailContainer')" + '"]){{/info}}{{/velo' + 'city}}')
241 #set($discard = $emailContainer.setContent($emailContainerContent))
242 #end
243 ##
244 ## Load messages into a Map by messageID.
245 #foreach($obj in $emailContainer.getObjects($config.get('emailClass')))
246 #set($discard = $mail.put($obj.getProperty('messageID').getValue(), $obj))
247 #end
248 #end
249 ##
250 #**
251 * Is a guest allowed to accept an invitation?
252 *
253 * $guestActionsDoc (Document) the document which guests will use to register.
254 *###
255 #macro(canGuestAcceptInvitation, $guestActionsDoc)
256 #set($out = 'true')
257 #if(!$xwiki.hasAccessLevel('register', 'XWiki.XWikiGuest', 'XWiki.XWikiPreferences')
258 && !$guestActionsDoc.hasProgrammingRights())
259 ##
260 #set($out = 'false')
261 #end
262 $out##
263 #end
264 ##
265 #**
266 * Get the action taken by the user.
267 * This will interpret actions taken using displayActionConfirmationForm
268 *
269 * $parameterMap (Map<String, String>) the parameter map gotten by calling getParameterMap on the servlet request.
270 *
271 * $actionOutList (List<String>) will be populated with a single value (the action)
272 *###
273 #macro(getUserAction, $parameterMap, $actionOutList)
274 #set($actionInternal = 0)
275 #foreach($param in $parameterMap.keySet())
276 #if($param.indexOf('doAction_') != -1)
277 ## Strip 'doAction_'
278 #set($actionInternal = $param.substring(9))
279 #end
280 #end
281 #if($actionInternal != 0)
282 #set($discard = $actionOutList.add($actionInternal))
283 #end
284 #end
285 ##
286 #*
287 * Display a form allowing a user to confirm doing an action.
288 *
289 * $messageIDs (List<String>) the unique IDs of the invitations to act upon.
290 *
291 * $action (String) the action to do.
292 *
293 * $memoLabel (String) what the memo field should be labeled.
294 *
295 * $confirmLabel (String) what the confirm button should say.
296 *
297 * $additionalParameters (Map<String, String>) these parameters will be xml escaped and placed in hidden input fields.
298 *###
299 #macro(displayActionConfirmationForm, $messageIDs, $action, $memoLabel, $confirmLabel, $additionalParameters)
300 {{html wiki=false clean=false}}
301 <div class="invitation action-confirm">
302 <form action="$doc.getURL()" method="POST">
303 ##
304 #foreach($id in $messageIDs)
305 <input type="hidden" name="messageID" value="$escapetool.xml($id)" />
306 #end
307 <input type="hidden" name="confirm" value="y" />
308 <input type="hidden" name="form_token" value="$!{services.csrf.getToken()}" />
309 #if($additionalParameters && $additionalParameters.size() > 0)
310 #foreach($param in $additionalParameters.keySet())
311 <input type="hidden" name="$escapetool.xml($param)" value="$escapetool.xml($additionalParameters.get($param))" />
312 #end
313 #end
314 ##
315 <dl>
316 <dt><label for="memo">$memoLabel</label></dt>
317 <dd><input type="text" size="54" name="memo" /></dd>
318 </dl>
319 <div class="bottombuttons">
320 <div class="buttons">
321 <span class="buttonwrapper">
322 <input type="submit" class="button" name="doAction_$escapetool.xml($action)" value="$confirmLabel" />
323 </span>
324 </div>
325 </div>
326 </form>
327 </div>
328 {{/html}}
329 #end
330 ##
331 #*
332 * Set the status of a message and log the memo.
333 *
334 * $message (Xobject) the message to act on.
335 *
336 * $status (String) the status to set the message to.
337 *
338 * $memo (String) what to enter in the log.
339 *###
340 #macro(setMessageStatus, $message, $status, $memo)
341 $message.set('status', $status)##
342 #set($history = $message.getProperty('history').getValue())
343 #set($statusWord = "#messageStatusForCode($status)")
344 ## disallow injection of \n which starts a new line or { which may be used for macros.
345 #set($log = $memo.replaceAll('\n', ' ').replaceAll('\{', '~{'))
346 #set($entry = "|$statusWord|[[$xcontext.getUser()]]|$!log")
347 #if("$!history" != '')
348 $message.set('history', "$!history$util.getNewline()$entry")##
349 #else
350 $message.set('history', $entry)##
351 #end
352 #end
353 ##
354 #*
355 * Get the last memo from the message history.
356 *
357 * $message (Xobject) the message to act on.
358 *###
359 #macro(getLastMemo, $message)
360 #set($history = "$!message.getProperty('history').getValue()")
361 #set($indexAfterLastNewline = $mathtool.add($history.lastIndexOf($util.getNewline()), 1))
362 #if($indexAfterLastNewline < $history.length())
363 #set($entry = "$!history.substring($indexAfterLastNewline)")
364 #set($indexAfterLastPipe = $mathtool.add($entry.lastIndexOf('|'), 1))
365 #if($indexAfterLastPipe < $entry.length())
366 $entry.substring($indexAfterLastPipe)##
367 #end
368 #end
369 #end
370 ##
371 #*
372 * Get the status of the current message for it's code.
373 * unsent - not sent yet.
374 * pending - sent and awating a response
375 * accepted - sent and accepted by recipient
376 * declined - sent and declined by recipient
377 * canceled - sent then canceled by sender
378 * reported - as spam (by recipient)
379 * notSpam - reported as spam and investigated (by admin)
380 * sendingFailed - failed to send message
381 * else - unknown status
382 *
383 * $status (String) the status of the message.
384 *###
385 #macro(messageStatusForCode, $status)
386 #if($status == 'unsent')
387 $services.localization.render('xe.invitation.messageStatus.unsent')##
388 #elseif($status == 'pending')
389 $services.localization.render('xe.invitation.messageStatus.pending')##
390 #elseif($status == 'accepted')
391 $services.localization.render('xe.invitation.messageStatus.accepted')##
392 #elseif($status == 'declined')
393 $services.localization.render('xe.invitation.messageStatus.declined')##
394 #elseif($status == 'canceled')
395 $services.localization.render('xe.invitation.messageStatus.canceled')##
396 #elseif($status == 'reported')
397 $services.localization.render('xe.invitation.messageStatus.reported')##
398 #elseif($status == 'notSpam')
399 $services.localization.render('xe.invitation.messageStatus.investigated')##
400 #elseif($status == 'sendingFailed')
401 $services.localization.render('xe.invitation.messageStatus.sendingFailed')##
402 #else
403 $services.localization.render('xe.invitation.messageStatus.unknown', [$escapetool.xml($status)])##
404 #end
405 #end
406 {{/velocity}}