Wiki source code of XWiki.ConfigurableClass
Show last authors
author | version | line-number | content |
---|---|---|---|
1 | {{velocity}} | ||
2 | #* | ||
3 | * This part takes the configuration from any documents containing XWiki.ConfigurableClass objects and creates a form | ||
4 | * for each. To includeForm this document, you may specify: | ||
5 | * | ||
6 | * $section - String - The section which we are administrating eg: "Registration", "Users", or "Import". | ||
7 | * If none is specified then it checks for a request parameter called "section" and uses that, | ||
8 | * if no parameter, then this code assumes that it is part of the admin icons sheet and adds icons | ||
9 | * for any section which is not in $sections, in that event, this code assumes it is being run | ||
10 | * inside of a <ul> block. | ||
11 | * | ||
12 | * $sections - List<String> - If section is not specified, any sections on this list will not have icons made for them | ||
13 | * the assumption being that the icons are already there. If section is specified then this | ||
14 | * is not taken into account and may safely be undefined. | ||
15 | * | ||
16 | * $currentDoc - String (document.fullName) - The administration document, users who don't have permission to edit | ||
17 | * it will not be able to include applications (possibly injecting | ||
18 | * arbitrary code.) if none specified then $doc.getFullName() is used. | ||
19 | * | ||
20 | * $globaladmin - boolean - If set true then we will assume we are administrationg the entire wiki. | ||
21 | * If not set then we look for a request parameter called "editor" if that exists and equals | ||
22 | * "globaladmin" then $globaladmin is true, if it doesn't exist then we check to see if | ||
23 | * $currentDoc.getFullName() equals "XWiki.XWikiPreferences". | ||
24 | * | ||
25 | * $doNotUnlockConfigurableDocuments - boolean - If true then this code will not make any attempt to unlock configurable | ||
26 | * documents. By default it does because it locks any document in the | ||
27 | * section which is being configured which would lead to a lot of stray | ||
28 | * locks if they weren't all cancelled. Only recommended if this page is | ||
29 | * being included twice in the same page. | ||
30 | *### | ||
31 | ## Constants: | ||
32 | #set($redirectParameter = 'xredirect') | ||
33 | #set($nameOfThisDocument = 'XWiki.ConfigurableClass') | ||
34 | ## | ||
35 | ## Form submission depends on this. | ||
36 | $xwiki.jsfx.use('js/xwiki/actionbuttons/actionButtons.js', true) | ||
37 | ## | ||
38 | #if(!$section) | ||
39 | #set($section = $request.getParameter('section')) | ||
40 | #end | ||
41 | #if(!$currentDoc) | ||
42 | #set($currentDoc = $doc.getFullName()) | ||
43 | #end | ||
44 | ## Get value of $globaladmin if not specified. | ||
45 | #if("$!globaladmin" == '') | ||
46 | #if($editor != 'globaladmin' | ||
47 | && $request.getParameter('editor') != 'globaladmin' | ||
48 | && $currentDoc != "XWiki.XWikiPreferences") | ||
49 | ## | ||
50 | #set($globaladmin = false) | ||
51 | #else | ||
52 | #set($globaladmin = true) | ||
53 | #end | ||
54 | #end | ||
55 | #set($currentSpace = $xwiki.getDocument("$currentDoc").getSpace()) | ||
56 | ## | ||
57 | ## This application should not run with programming rights because it evaluates code which may not be trustworthy. | ||
58 | ## Removing the next line will open a security hole. | ||
59 | #sandboxDocument() | ||
60 | ## | ||
61 | ## This application locks every document in a section while that section is being edited so we should | ||
62 | ## check for locks held by the current user on any of the applications configured here and remove them. | ||
63 | #if(!$doNotUnlockConfigurableDocuments) | ||
64 | #set($outputList = []) | ||
65 | #findNamesOfAppsToConfigure("", $globaladmin, $currentSpace, $outputList)## | ||
66 | ## We don't want to generate javascript which unlocks the current document just after we got finished locking it. | ||
67 | #set($discard = $outputList.remove($currentDoc)) | ||
68 | #unlockDocuments($outputList) | ||
69 | #end | ||
70 | ## | ||
71 | ##------------------------------------------------------------------------------------------------------------ | ||
72 | ## If $section exists then we are viewing the admin page for a perticular section. | ||
73 | ## eg: 'Registration', 'Presentation', 'Import' etc. | ||
74 | ##------------------------------------------------------------------------------------------------------------ | ||
75 | ## | ||
76 | #if($section && $section != '') | ||
77 | ## | ||
78 | ## This is for keeping track of whether we have shown the heading yet or not. | ||
79 | ## If the heading doesn't need to be shown, but an error occurs in processing, then we show the heading | ||
80 | ## so that the user knows what the error relates to. | ||
81 | #set($headingShowing = false) | ||
82 | ## | ||
83 | ## Searches the database for names of apps to be configured | ||
84 | #set($outputList = []) | ||
85 | #findNamesOfAppsToConfigure($section, $globaladmin, $xwiki.getDocument("$currentDoc").getSpace(), $outputList) | ||
86 | ## | ||
87 | #if($outputList.size() > 0) | ||
88 | ## Merge save buttons, remove headings from subsections, and make information links into popups. | ||
89 | $xwiki.jsx.use($nameOfThisDocument) | ||
90 | #end | ||
91 | ## | ||
92 | #foreach($appName in $outputList) | ||
93 | ## | ||
94 | ## Make sure the current user has permission to edit the configurable application. | ||
95 | #set($userHasAccessToDocument = $xcontext.hasAccessLevel('edit', $appName)) | ||
96 | ## | ||
97 | ## If the document was not last saved by a user with edit privilage on this page | ||
98 | ## then we can't safely display the page but we should warn the viewer. | ||
99 | #if($userHasAccessToDocument) | ||
100 | ## Get the configurable application | ||
101 | #set($app = $xwiki.getDocument($appName)) | ||
102 | ## | ||
103 | #set($documentSavedByAuthorizedUser = false) | ||
104 | #checkDocumentSavedByAuthorizedUser($app, $currentDoc, $documentSavedByAuthorizedUser) | ||
105 | #end | ||
106 | ## Will we have to display an error message? | ||
107 | #set($displayError = !$userHasAccessToDocument || !$documentSavedByAuthorizedUser) | ||
108 | ## | ||
109 | ## There is no need to display a heading unless: | ||
110 | ## 1. There was already a section before this document. | ||
111 | ## 2. This is not the first document in this section. | ||
112 | ## | ||
113 | ## If we are displaying the heading and there is an error to be shown Javascript will not strip the heading. | ||
114 | #if(!$appName.equals($outputList.get(0)) || $sections.contains($section)) | ||
115 | ## Create a document heading. | ||
116 | #showHeading($appName, $displayError, $headingShowing) | ||
117 | #end | ||
118 | ## | ||
119 | #if(!$userHasAccessToDocument) | ||
120 | #showHeading($appName, true, $headingShowing) | ||
121 | |||
122 | {{error}}$msg.get('xe.admin.configurable.noPermissionThisApplication'){{/error}} | ||
123 | |||
124 | #else | ||
125 | ## | ||
126 | #if(!$documentSavedByAuthorizedUser) | ||
127 | #showHeading($appName, true, $headingShowing) | ||
128 | |||
129 | {{error}}$msg.get('xe.admin.configurable.applicationAuthorNoAdmin', [$app.Author]){{/error}} | ||
130 | |||
131 | #else | ||
132 | ## | ||
133 | ## Locking document | ||
134 | ##------------------------------------------------------------------------------------------------------------ | ||
135 | #if($app.getLocked()) | ||
136 | #set($locked = true) | ||
137 | #end | ||
138 | ## If the document is locked and not by the current user and forceEdit is not set true, | ||
139 | #if($locked && $app.getLockingUser() != $xcontext.getUser() && !$request.getParameter('forceEdit')) | ||
140 | #set($requestURL = "$request.getRequestURL()") | ||
141 | #if($requestURL.indexOf("?") == -1) | ||
142 | #set($requestURL = "${requestURL}?") | ||
143 | #end | ||
144 | #showHeading($appName, true, $headingShowing) | ||
145 | |||
146 | {{error}}$msg.get("doclockedby") $app.getLockingUser() [[$msg.get("forcelock")>>${requestURL}&forceEdit=1]]{{/error}} | ||
147 | |||
148 | #else | ||
149 | ## If the document is not already locked, attempt to aquire the lock. | ||
150 | #if(!$locked) | ||
151 | ## Try to use an ajax call to lock the document. | ||
152 | {{html clean=false wiki=true}}</p> | ||
153 | <noscript> | ||
154 | |||
155 | {{warning}}$msg.get('xe.admin.configurable.cannotLockNoJavascript'){{/warning}} | ||
156 | |||
157 | </noscript> | ||
158 | <script type="text/javascript"> | ||
159 | document.observe("dom:loaded", function() { | ||
160 | new Ajax.Request("$xwiki.getURL($app.getFullName(), 'lock', 'ajax=1')"); | ||
161 | }); | ||
162 | </script> | ||
163 | <p>{{/html}} | ||
164 | #set($discard = $lockedDocumentNames.add($app.getFullName())) | ||
165 | #end | ||
166 | ##------------------------------------------------------------------------------------------------------------ | ||
167 | ## Done Locking. | ||
168 | ## | ||
169 | ## Get all objects of the "ConfigurableClass" from this document. | ||
170 | #set($allConfigurableObjs = $app.getObjects($nameOfThisDocument)) | ||
171 | ## Seperate out the objects which are for this section. | ||
172 | #set($configurableObjs = []) | ||
173 | #foreach($configurableObj in $allConfigurableObjs) | ||
174 | #if($app.getValue('displayInSection', $configurableObj) == $section) | ||
175 | ## If this is space admin, then don't display global, if global don't display space. | ||
176 | #if($globaladmin == ($app.getValue('configureGlobally', $configurableObj) == 1)) | ||
177 | #set($discard = $configurableObjs.add($configurableObj)) | ||
178 | #end | ||
179 | #end | ||
180 | #end | ||
181 | #if($configurableObjs.size() == 0) | ||
182 | ## Internal error, not translated. | ||
183 | #showHeading($appName, true, $headingShowing) | ||
184 | |||
185 | {{error}}Internal error: All objects were filtered out for application: $appName.{{/error}} | ||
186 | |||
187 | #else | ||
188 | #set($formAction = "$xwiki.getURL($app.getFullName(), 'save')") | ||
189 | #set($formId = "$section.toLowerCase()_$app.getFullName()") | ||
190 | #set($escapedAppName = $escapetool.html($app.getFullName())) | ||
191 | #foreach($configurableObj in $configurableObjs) | ||
192 | ## Display the header if one exists. | ||
193 | #set($heading = $app.getValue('heading', $configurableObj)) | ||
194 | #if($heading && $heading != '') | ||
195 | == #evaluate($heading) == | ||
196 | #end | ||
197 | ## If the class specifies custom code to evaluate, | ||
198 | ## then close the html macro, evaluate it and reopen the macro. | ||
199 | #set($codeToExecute = "$!app.getValue('codeToExecute', $configurableObj)") | ||
200 | #if($codeToExecute != '') | ||
201 | #evaluate($codeToExecute) | ||
202 | #end | ||
203 | ## | ||
204 | ## If propertiesToShow is set, then we will only show the properties contained therein. | ||
205 | #set($propertiesToShow = $app.getValue('propertiesToShow', $configurableObj)) | ||
206 | #if(!$propertiesToShow || $propertiesToShow.getClass().getName().indexOf('List') == -1) | ||
207 | #set($propertiesToShow = []) | ||
208 | #end | ||
209 | ## | ||
210 | ## If linkPrefix is set, then we will make each property label a link which starts with that prefix. | ||
211 | #set($linkPrefix = "$!app.getValue('linkPrefix', $configurableObj)") | ||
212 | ## | ||
213 | ## If the Configurable object specifies a configuration class, use it, | ||
214 | ## otherwise assume custom forms are used instead. | ||
215 | #set($configClassName = "$!app.getValue('configurationClass', $configurableObj)") | ||
216 | #if($configClassName != '') | ||
217 | #set($objClass = $xwiki.getDocument("$configClassName").getxWikiClass()) | ||
218 | #if(!$objClass || $objClass.getClass().getName().indexOf('.Class') == -1) | ||
219 | #showHeading($appName, true, $headingShowing) | ||
220 | |||
221 | {{error}}$msg.get('xe.admin.configurable.configurationClassNonexistant'){{/error}} | ||
222 | |||
223 | #else | ||
224 | ## Use the first object from the document which is of the configuration class. | ||
225 | #set($obj = $app.getObject($objClass.getName())) | ||
226 | ## | ||
227 | #if(!$obj || $obj.getClass().getName().indexOf('.Object') == -1) | ||
228 | #showHeading($appName, true, $headingShowing) | ||
229 | |||
230 | {{error}} | ||
231 | $msg.get('xe.admin.configurable.noObjectOfConfigurationClassFound', | ||
232 | [$objClass.getName(), $app.getFullName()]) | ||
233 | {{/error}} | ||
234 | |||
235 | #else | ||
236 | #define($formHtml) | ||
237 | ## We don't begin the form until we have content for it so that a configurable can specify a | ||
238 | ## custom form in codeToExecute and if that configurable object is the first of it's kind in that | ||
239 | ## document, the custom form will not be put inside of our form. | ||
240 | #if(!$insideForm) | ||
241 | <form id="$formId" method="post" action="$formAction" onsubmit="cancelCancelEdit()"> | ||
242 | <fieldset> | ||
243 | #set($insideForm = true) | ||
244 | #end | ||
245 | #foreach($propName in $objClass.getPropertyNames()) | ||
246 | #if($propertiesToShow.size() > 0 && !$propertiesToShow.contains($propName)) | ||
247 | ## Silently skip over this property. | ||
248 | #else | ||
249 | <p> | ||
250 | #set($prettyName = "#evaluate($app.displayPrettyName($propName, $obj))") | ||
251 | ## App Name is prepended to for= to make label work with id which is modified to prevent collisions. | ||
252 | <label for="${escapedAppName}_$objClass.getName()_0_$propName"> | ||
253 | #if($linkPrefix != '') | ||
254 | #set($linkScript = "$linkPrefix$propName") | ||
255 | <a href="$escapetool.html("#evaluate($linkScript)")">$escapetool.html($prettyName)</a> | ||
256 | #else | ||
257 | $escapetool.html($prettyName) | ||
258 | #end | ||
259 | </label> | ||
260 | $obj.display($propName, "edit") | ||
261 | </p> | ||
262 | #end## If property is in propertiesToShow | ||
263 | #end## Foreach property in this class | ||
264 | #end## define $formHtml | ||
265 | ## Strip pre tags and html macro invocations which $obj.display inserts. | ||
266 | ## then prepend application name to ids to prevent id collissions. | ||
267 | |||
268 | {{html clean="false" wiki="false"}}</p> | ||
269 | $formHtml.toString().replaceAll('\{\{[/]?html[^}]*\}\}|<[/]?pre>', '').replaceAll(" id='", " id='${escapedAppName}_") | ||
270 | <p>{{/html}}## | ||
271 | |||
272 | #end## If object exists | ||
273 | #end## If class exists | ||
274 | #end## If class name is specified. | ||
275 | #end## Foreach configurable object found in this document | ||
276 | ## If a form was started then we end it. | ||
277 | #if($insideForm) | ||
278 | |||
279 | {{html clean="false" wiki="false"}}</p> | ||
280 | ## We add in a redirect field to prevent the user from being carried away when they save | ||
281 | ## if they don't have javascript. | ||
282 | #set($thisURL = $request.getRequestURL()) | ||
283 | #if($request.getQueryString() && $request.getQueryString().length() > 0) | ||
284 | #set($thisURL = "${thisURL}?$request.getQueryString()") | ||
285 | #end | ||
286 | <input type="hidden" id="${escapedAppName}_redirect" name="$redirectParameter" value="$escapetool.html($thisURL)" /> | ||
287 | </fieldset> | ||
288 | <div class="bottombuttons"> | ||
289 | <p class="admin-buttons"> | ||
290 | <span class="buttonwrapper"> | ||
291 | ## Text to display on the button. If there is a heading then this button should be labeled | ||
292 | ## that it is for saving this section. Otherwise it should be a generic "save" button. | ||
293 | #if($headingShowing) | ||
294 | #set($buttonText = "$msg.get('admin.save') $escapedAppName") | ||
295 | #else | ||
296 | #set($buttonText = "$msg.get('admin.save')") | ||
297 | #end | ||
298 | <input class="button" type="submit" name="action_saveandcontinue" value="$buttonText" /> | ||
299 | </span> | ||
300 | </p> | ||
301 | </div> ## bottombuttons | ||
302 | </form> | ||
303 | #set($insideForm = false) | ||
304 | <p>{{/html}} | ||
305 | |||
306 | #end | ||
307 | #end## If there are configurable objects | ||
308 | #end## If document is not locked or forceEdit is enabled | ||
309 | #end## If app author has permission to edit admin page | ||
310 | #end## If the current user has permission to edit the configurable application. | ||
311 | #end## Foreach document name in names to configure | ||
312 | |||
313 | {{html clean=false wiki=false}} | ||
314 | <script type="text/javascript"> | ||
315 | /* <![CDATA[ */ | ||
316 | ## Alt+Shift+S presses the first saveAndContinue button it finds, not what we want so we will disable edit shortcuts. | ||
317 | XWiki.actionButtons.EditActions = Object.extend(XWiki.actionButtons.EditActions, {addShortcuts : function() { }}); | ||
318 | ## | ||
319 | ## TODO: cancel and "submit all" buttons. | ||
320 | //]]> | ||
321 | </script> | ||
322 | {{/html}} | ||
323 | |||
324 | ## | ||
325 | #else | ||
326 | ## | ||
327 | ##------------------------------------------------------------------------------------------------------------ | ||
328 | ## If section is not set then we are viewing the main administration page. | ||
329 | ##------------------------------------------------------------------------------------------------------------ | ||
330 | ## | ||
331 | ## If there is no list called sections then we set sections to an empty list. | ||
332 | #if(!$sections || $sections.getClass().getName().indexOf("List") == -1) | ||
333 | #set($sections = []) | ||
334 | #end | ||
335 | ## | ||
336 | ## We have to create a list of documents which the current user doesn't have permission to view. | ||
337 | ## So we can add an error messsage to the bottom of the page if there are any. | ||
338 | #set($appsUserCannotView = []) | ||
339 | ## | ||
340 | ## A list of sections (to be added) which the user is not allowed to edit, icons will be displayed with a message | ||
341 | #set($sectionsUserCannotEdit = []) | ||
342 | ## List of sections to be added, in order by creationDate of oldest contained application. | ||
343 | #set($sectionsToAdd = []) | ||
344 | ## Map of URL of icon to use by the name of the section to use that icon on. | ||
345 | #set($iconBySection = {}) | ||
346 | ## | ||
347 | #set($outputList = []) | ||
348 | #findNamesOfAppsToConfigure("", $globaladmin, $currentSpace, $outputList) | ||
349 | ## | ||
350 | #foreach($appName in $outputList) | ||
351 | ## | ||
352 | ## Get the configurable application | ||
353 | #set($app = $xwiki.getDocument($appName)) | ||
354 | ## | ||
355 | ## If getDocument returns null, then warn the user that they don't have view access to that application. | ||
356 | #if(!$app) | ||
357 | #set($discard = $appsUserCannotView.add($appName)) | ||
358 | #end | ||
359 | ## | ||
360 | #set($configurableObjects = $app.getObjects($nameOfThisDocument)) | ||
361 | #foreach($configurableObject in $configurableObjects) | ||
362 | #set($displayInSection = $app.getValue('displayInSection', $configurableObject)) | ||
363 | ## | ||
364 | ## If there is no section for this configurable or if the section cannot be edited, then check if the | ||
365 | ## application can be edited by the current user, if so then we display the icon from the current app and | ||
366 | ## don't display any message to tell the user they can't edit that section. | ||
367 | #if(!$sections.contains($displayInSection) || $sectionsUserCannotEdit.contains($displayInSection)) | ||
368 | ## | ||
369 | ## If there is no section for this configurable, then we will have to add one. | ||
370 | #if(!$sections.contains($displayInSection) && !$sectionsToAdd.contains($displayInSection)) | ||
371 | #set($discard = $sectionsToAdd.add($displayInSection)) | ||
372 | #end | ||
373 | ## | ||
374 | ## If an attachment by the filename iconAttachment exists and is an image | ||
375 | #set($attachment = $app.getAttachment("$app.getValue('iconAttachment', $configurableObject)")) | ||
376 | #if($attachment && $attachment.isImage()) | ||
377 | ## Set the icon for this section as the attachment URL. | ||
378 | #set($discard = $iconBySection.put($displayInSection, $app.getAttachmentURL($attachment.getFilename()))) | ||
379 | #end | ||
380 | ## | ||
381 | ## If the user doesn't have edit access to the application, we want to should show a message on the icon | ||
382 | #if(!$xcontext.hasAccessLevel("edit", $app.getFullName())) | ||
383 | #if(!$sectionsUserCannotEdit.contains($displayInSection)) | ||
384 | #set($discard = $sectionsUserCannotEdit.add($displayInSection)) | ||
385 | #end | ||
386 | #elseif($sectionsUserCannotEdit.contains($displayInSection)) | ||
387 | ## If the user didn't have access to the section before but does have access to _this_ app which is | ||
388 | ## configured in the section, then the section becomes accessable. | ||
389 | #set($discard = $sectionsUserCannotEdit.remove($displayInSection)) | ||
390 | #end | ||
391 | #end## If section doesn't exist or user doesn't have access. | ||
392 | #end## Foreach configurable object in this app. | ||
393 | #end## Foreach application which is configurable. | ||
394 | ## | ||
395 | ## Now we go through sectionsToAdd and generate icons for them | ||
396 | #set($defaultIcon = $xwiki.getAttachmentURL($nameOfThisDocument, 'DefaultAdminSectionIcon.png')) | ||
397 | #if($globaladmin) | ||
398 | #set($queryString = "editor=globaladmin&section=") | ||
399 | #else | ||
400 | #set($queryString = "space=${currentSpace}&section=") | ||
401 | #if($request.getParameter('editor')) | ||
402 | #set($queryString = "editor=$escapetool.url($request.getParameter('editor'))&$queryString") | ||
403 | #end | ||
404 | #end | ||
405 | |||
406 | {{html clean=false wiki=false}} | ||
407 | #foreach($sectionToAdd in $sectionsToAdd) | ||
408 | #set($icon = $iconBySection.get($sectionToAdd)) | ||
409 | #if(!$icon) | ||
410 | #set($icon = $defaultIcon) | ||
411 | #end | ||
412 | <li class="$escapetool.html($sectionToAdd).replaceAll(' ', '_')"> | ||
413 | #set($hasAccess = !$sectionsUserCannotEdit.contains($sectionToAdd)) | ||
414 | #if($hasAccess) | ||
415 | <a href="$xwiki.getURL($currentDoc, $xcontext.getAction(), "$queryString$escapetool.url($sectionToAdd)")"> | ||
416 | #else | ||
417 | <a title="$msg.get('xe.admin.configurable.sectionIconNoAccessTooltip')"> | ||
418 | #end | ||
419 | <img src="$icon" alt="$escapetool.html($sectionToAdd) icon"/> | ||
420 | $escapetool.html($sectionToAdd) | ||
421 | #if(!$hasAccess) | ||
422 | <br/><span class="errormessage">$msg.get('xe.admin.configurable.sectionIconNoAccess')</span> | ||
423 | #end | ||
424 | </a> | ||
425 | </li> | ||
426 | #end | ||
427 | {{/html}} | ||
428 | |||
429 | ## Finally we display an error message if there are any applications which we were unable to view. | ||
430 | #if($appsUserCannotView.size() > 0) | ||
431 | |||
432 | {{error}}$msg.get('xe.admin.configurable.noViewAccessSomeApplications', [$appsUserCannotView]){{/error}} | ||
433 | |||
434 | #end | ||
435 | #end## If we should be looking at the main administration page. | ||
436 | ## | ||
437 | ##------------------------------------------------------------------------------------------------------------ | ||
438 | ## The Macros, nothing below this point is run directly. | ||
439 | ##------------------------------------------------------------------------------------------------------------ | ||
440 | ## | ||
441 | #* | ||
442 | * | ||
443 | * Any documents which are on the provided list ($documentNames) which are locked by the current user will be unlocked. | ||
444 | * If this macro has programming rights, then they are unlocked programmatically, otherwise a javascript tag is | ||
445 | * generated with ajax calls to cancel for all of the documents. If there are documents on this list which are not | ||
446 | * locked by the current user, then they are ignored. | ||
447 | * | ||
448 | * @param $documentNames - List<String> - fullNames of documents which should be unlocked if they are locked by the | ||
449 | * current user. | ||
450 | *### | ||
451 | #macro(unlockDocuments $documentNames) | ||
452 | #if($documentNames.size() > 0) | ||
453 | #set($sql = "doc.fullName=") | ||
454 | #foreach($documentName in $documentNames) | ||
455 | #set($sql = "${sql}'$documentName' or doc.fullName=") | ||
456 | #end | ||
457 | ## Trim the dangling ' or doc.fullName=?' | ||
458 | #set($sql = $sql.substring(0, $sql.lastIndexOf(' or doc.fullName='))) | ||
459 | #set($sql = ", XWikiLock lock where lock.docId=doc.id and lock.userName='$xcontext.getUser()' and (${sql})") | ||
460 | #set($namesOfdocumentsToUnlock = $xwiki.searchDocuments($sql)) | ||
461 | ## Use ajax and hope the user runs javascript. | ||
462 | {{html clean=false wiki=false}} | ||
463 | <script type="text/javascript"> | ||
464 | document.observe("dom:loaded", function() { | ||
465 | #foreach($nameOflockedDocument in $namesOfdocumentsToUnlock) | ||
466 | new Ajax.Request("$xwiki.getURL($nameOflockedDocument, 'cancel', 'ajax=1')"); | ||
467 | #end | ||
468 | }); | ||
469 | </script> | ||
470 | {{/html}}## | ||
471 | #end## If output list size > 0 | ||
472 | #end## Macro | ||
473 | ## | ||
474 | #* | ||
475 | * Find names of documents which contain objects of the class 'XWiki.ConfigurableClass' | ||
476 | * | ||
477 | * @param $section - String - Look for apps which specify that they should be configured in this section, | ||
478 | * if null or "" then returns them for all sections. | ||
479 | * | ||
480 | * @param $globaladmin - boolean - If true then we will look for applications which should be configured globally. | ||
481 | * | ||
482 | * @param $space - String - If not looking for apps which are configured globally, then this is the space where we | ||
483 | * will look for apps in. If null or "" or if $globaladmin is true, then all spaces will be | ||
484 | * searched. | ||
485 | * | ||
486 | * @param $outputList - List - The returns from this macro will be put in this list, passing the list as a parameter | ||
487 | * a safety measure because macros can't return values. | ||
488 | *### | ||
489 | #macro(findNamesOfAppsToConfigure, $section, $globaladmin, $space, $outputList) | ||
490 | ## Use a parameterized sql query to prevent injection. | ||
491 | #set($params = []) | ||
492 | #if($section && $section != '') | ||
493 | #set($discard = $params.add("$section")) | ||
494 | #set($sqlA = ' StringProperty as section,') | ||
495 | #set($sqlB = " and section.id=obj.id and section.name='displayInSection' and section.value=?") | ||
496 | #else | ||
497 | ## Make sure they are "" in case they were set prior to calling the macro. | ||
498 | #set($sqlA = '') | ||
499 | #set($sqlB = '') | ||
500 | #end | ||
501 | ## Set up query based on value of $globaladmin | ||
502 | #if($globaladmin == true) | ||
503 | #set($sqlC = '1') | ||
504 | #else | ||
505 | #if($space && $space != '') | ||
506 | #set($sqlC = '0 and doc.space = ?') | ||
507 | #set($discard = $params.add($space)) | ||
508 | #else | ||
509 | #set($sqlC = '0') | ||
510 | #end | ||
511 | #end | ||
512 | #set($sql = ", BaseObject as obj,$sqlA IntegerProperty as global where " | ||
513 | + "doc.fullName=obj.name and obj.className='" + $nameOfThisDocument + "'$sqlB " | ||
514 | + "and global.id=obj.id and global.name='configureGlobally' and global.value=$sqlC " | ||
515 | + "order by doc.creationDate") | ||
516 | ## | ||
517 | ## Run the search | ||
518 | #set($outputList = $xwiki.searchDocuments($sql, 0, 0, $params)) | ||
519 | ## | ||
520 | #end | ||
521 | ## | ||
522 | #* | ||
523 | * If this document is saved with programming access or is includeForm'd into a document with programming, we have to | ||
524 | * drop programming rights in order for it to run safely because it evaluates potentially untrustworthy code. | ||
525 | *### | ||
526 | #macro(sandboxDocument) | ||
527 | #if($xcontext.hasProgrammingRights()) | ||
528 | $xcontext.getContext().getDoc().setContentAuthor('XWiki.XWikiGuest')## | ||
529 | #end | ||
530 | #end | ||
531 | ## | ||
532 | #* | ||
533 | * Try to determine whether a document was edited by a user who has edit right on this page. This is trickey because | ||
534 | * documents are imported with the name XWiki.XWikiGuest who has no access to anything after import. | ||
535 | * | ||
536 | * @param theDoc - Document who's editor should be checked for edit access on this document. | ||
537 | *### | ||
538 | #macro(checkDocumentSavedByAuthorizedUser, $docToCheck, $currentDoc, $hasAccess) | ||
539 | ## The system is started and the only user is XWikiGuest who has admin right but gives it up when he imports the default | ||
540 | ## documents, we are checking to see if this looks like the guest imported the document with the first import. | ||
541 | #if($docToCheck.getWiki() == $xcontext.getMainWikiName() | ||
542 | && $docToCheck.getVersion() == '1.1' | ||
543 | && $docToCheck.getCreator() != $docToCheck.getContentAuthor() | ||
544 | && $docToCheck.getContentAuthor() == 'XWiki.XWikiGuest') | ||
545 | ## | ||
546 | #set($userToCheck = $docToCheck.getCreator()) | ||
547 | #else | ||
548 | #set($userToCheck = $docToCheck.getAuthor()) | ||
549 | #end | ||
550 | #set($hasAccess = $xwiki.hasAccessLevel("edit", $userToCheck, $currentDoc)) | ||
551 | #end | ||
552 | ## | ||
553 | #* | ||
554 | * Show the heading for configuration for a given application. | ||
555 | * | ||
556 | * $appName (String) Name of the application to show configuration heading for. | ||
557 | * | ||
558 | * $displayError (boolean) If true, then the heading will be class="applicationHeading errorMessage" and javascript | ||
559 | * will know not to remove it when it is merging forms. | ||
560 | * | ||
561 | * $headingAlreadyShowing (boolean) If true then we don't make another heading. Otherwise it is set to true. | ||
562 | *### | ||
563 | #macro(showHeading, $appName, $displayError, $headingAlreadyShowing) | ||
564 | #if(!$headingAlreadyShowing) | ||
565 | #set($headingAlreadyShowing = true) | ||
566 | ## If we are to display an error message, the class should be changed so that javascript doesn't remove the | ||
567 | ## heading from over the error message. | ||
568 | #* | ||
569 | #if($displayError) | ||
570 | (%class="applicationHeading errorMessage"%) | ||
571 | #else | ||
572 | (%class="applicationHeading"%) | ||
573 | #end*### | ||
574 | |||
575 | = $msg.get("admin.customize") __[[$appName>>$appName]]__: = | ||
576 | ## (%%) | ||
577 | #end | ||
578 | #end | ||
579 | {{/velocity}} |