Version 2.1 par Florent Charton le 2024/08/08 18:43

Afficher les derniers auteurs
1 {{include reference="XWiki.ConfigurableClassMacros" /}}
2
3 {{velocity}}
4 #*
5 * This part takes the configuration from any documents containing XWiki.ConfigurableClass objects and creates a form
6 * for each. To includeForm this document, you may specify:
7 *
8 * $section - String - The section which we are administrating eg: "Registration", "Users", or "Import".
9 * If none is specified then it checks for a request parameter called "section" and uses that,
10 * if no parameter, then this code assumes that it is part of the admin icons sheet and adds icons
11 * for any section which is not in $sections, in that event, this code assumes it is being run
12 * inside of a <ul> block.
13 *
14 * $sections - List<String> - If section is not specified, any sections on this list will not have icons made for them,
15 * the assumption being that the icons are already there. If section is specified then this
16 * is not taken into account and may safely be undefined.
17 *
18 * $currentDoc - String (document.fullName) - The administration document, users who don't have permission to edit
19 * it will not be able to include applications (possibly injecting
20 * arbitrary code.) if none specified then $doc.getFullName() is used.
21 *
22 * $globaladmin - boolean - If set true then we will assume we are administrationg the entire wiki.
23 * If not set then we look for a request parameter called "editor" if that exists and equals
24 * "globaladmin" then $globaladmin is true, if it doesn't exist then we check to see if
25 * $currentDoc.getFullName() equals "XWiki.XWikiPreferences".
26 *###
27 ##
28 ## Form submission depends on this.
29 $xwiki.jsfx.use('js/xwiki/actionbuttons/actionButtons.js', true)
30 ## In case of conflict issue we want to display the diff properly
31 #set ($discard = $xwiki.ssfx.use('uicomponents/viewers/diff.css', true))
32 #set ($discard = $xwiki.jsfx.use('uicomponents/viewers/diff.js'))
33 ##
34 #if(!$section)
35 #set($section = $request.getParameter('section'))
36 #end
37 #if(!$currentDoc)
38 #set($currentDoc = $doc.getFullName())
39 #end
40 ## Get value of $globaladmin if not specified.
41 #if("$!globaladmin" == '')
42 #if($editor != 'globaladmin'
43 && $request.getParameter('editor') != 'globaladmin'
44 && $currentDoc != 'XWiki.XWikiPreferences')
45 ##
46 #set($globaladmin = false)
47 #else
48 #set($globaladmin = true)
49 #end
50 #end
51 #set($currentSpace = $xwiki.getDocument($currentDoc).getSpace())
52 ##
53 ##------------------------------------------------------------------------------------------------------------
54 ## If $section exists then we are viewing the admin page for a particular section.
55 ## eg: 'Registration', 'Presentation', 'Import' etc.
56 ##------------------------------------------------------------------------------------------------------------
57 ##
58 #if($section && $section != '')
59 ##
60 ## This is for keeping track of whether we have shown the heading yet or not.
61 ## If the heading doesn't need to be shown, but an error occurs in processing, then we show the heading
62 ## so that the user knows what the error relates to.
63 #set($headingShowing = false)
64 ##
65 ## Searches the database for names of apps to be configured
66 #set($outputList = [])
67 #findNamesOfAppsToConfigure($section, $globaladmin, $xwiki.getDocument($currentDoc).getSpace(), $outputList)
68 ##
69 #foreach($appName in $outputList)
70 ##
71 ## Make sure the current user has permission to edit the configurable application.
72 #set($userHasAccessToDocument = $xcontext.hasAccessLevel('edit', $appName))
73 ##
74 ## If the document was not last saved by a user with edit privilege on this page
75 ## then we can't safely display the page but we should warn the viewer.
76 #if($userHasAccessToDocument)
77 ## Get the configurable application
78 #set($app = $xwiki.getDocument($appName))
79 ##
80 #set($documentSavedByAuthorizedUser = false)
81 #checkDocumentSavedByAuthorizedUser($app, $currentDoc, $documentSavedByAuthorizedUser)
82 #end
83 ##
84 ## There is no need to display a heading unless:
85 ## 1. There was already a section before this document.
86 ## 2. This is not the first document in this section.
87 ##
88 ## If we are displaying the heading and there is an error to be shown Javascript will not strip the heading.
89 #if(!$appName.equals($outputList.get(0)) || $sections.contains($section))
90 ## Create a document heading.
91 #showHeading($appName, $headingShowing)
92 #end
93 ##
94 #if(!$userHasAccessToDocument)
95 #showHeading($appName, $headingShowing)
96
97 {{error}}{{translation key="xe.admin.configurable.noPermissionThisApplication"/}}{{/error}}
98
99 #elseif(!$documentSavedByAuthorizedUser)
100 #showHeading($appName, $headingShowing)
101
102 {{error}}{{translation key="xe.admin.configurable.applicationAuthorNoAdmin" parameters="$app.Author"/}}{{/error}}
103
104 ##
105 ##------------------------------------------------------------------------------------------------------------
106 ## If the document is locked and not by the current user and forceEdit is not set true,
107 #elseif($app.getLocked() && $app.getLockingUser() != $xcontext.getUser() && !$request.getParameter('forceEdit'))
108 #set($requestURL = "$request.getRequestURL()")
109 #if($requestURL.indexOf('?') == -1)
110 #set($requestURL = "${requestURL}?$request.queryString")
111 #end
112 #showHeading($appName, $headingShowing)
113
114 {{error}}{{translation key="doclockedby"/}} $app.getLockingUser() [[{{translation key="forcelock"/}}>>${requestURL}&forceEdit=1]]{{/error}}
115
116 #else
117 ## If the document is not already locked, attempt to acquire the lock.
118 #if(!$app.getLocked())
119
120 {{html wiki=true}}
121 <noscript>
122
123 {{warning}}{{translation key="xe.admin.configurable.cannotLockNoJavascript"/}}{{/warning}}
124
125 </noscript>
126 {{/html}}
127
128 {{html clean=false}}
129 <script>
130 document.observe("xwiki:dom:loaded", function() {
131 XWiki.DocumentLock && new XWiki.DocumentLock('$escapetool.javascript($app.prefixedFullName)').lock();
132 });
133 </script>
134 {{/html}}
135 #end
136 ##------------------------------------------------------------------------------------------------------------
137 ## Done Locking.
138 ##
139 ## Get all objects of the "ConfigurableClass" from this document.
140 #set($allConfigurableObjs = $app.getObjects($nameOfThisDocument))
141 ## Separate out the objects which are for this section.
142 #set($configurableObjs = [])
143 #foreach($configurableObj in $allConfigurableObjs)
144 #if($app.getValue('displayInSection', $configurableObj) == $section)
145 #set($discard = $configurableObjs.add($configurableObj))
146 #end
147 #end
148 #if($configurableObjs.size() == 0)
149 ## Internal error, not translated.
150 #showHeading($appName, $headingShowing)
151
152 {{error}}Internal error: All objects were filtered out for application:
153 $services.rendering.escape($appName, 'xwiki/2.1').{{/error}}
154
155 #else
156 #set($formAction = $xwiki.getURL($app.getFullName(), 'save'))
157 #set($formId = "${section.toLowerCase()}_${app.getFullName()}")
158 #set($escapedAppName = $escapetool.xml($app.getFullName()))
159 #foreach($configurableObj in $configurableObjs)
160 #set ($heading = $app.getValue('heading', $configurableObj))
161 #set ($codeToExecute = "$!app.getValue('codeToExecute', $configurableObj)")
162 ## If linkPrefix is set, then we will make each property label a link which starts with that prefix.
163 #set ($linkPrefix = "$!app.getValue('linkPrefix', $configurableObj)")
164 #if (!$app.restricted)
165 #set ($evaluatedConfigurableObj = $configurableObj.evaluate())
166 #set ($heading = $evaluatedConfigurableObj.heading)
167 #set ($linkPrefix = $evaluatedConfigurableObj.linkPrefix)
168 #end
169 ## Display the header if one exists.
170 #if($heading && $heading != '')
171 == $services.rendering.escape($heading, 'xwiki/2.1') ==
172 #end
173 ## Display code to execute
174 #if ($codeToExecute != '')
175 (%class="codeToExecute"%)(((##
176 $configurableObj.display('codeToExecute', 'view', false)
177 )))
178 #end
179 ##
180 ## If propertiesToShow is set, then we will only show the properties contained therein.
181 #set($propertiesToShow = $app.getValue('propertiesToShow', $configurableObj))
182 #if(!$propertiesToShow || $propertiesToShow.getClass().getName().indexOf('List') == -1)
183 #set($propertiesToShow = [])
184 #end
185 ##
186 ## If the Configurable object specifies a configuration class, use it,
187 ## otherwise assume custom forms are used instead.
188 #set($configClassName = "$!app.getValue('configurationClass', $configurableObj)")
189 #if($configClassName != '')
190 #set($objClass = $xwiki.getDocument($configClassName).getxWikiClass())
191 #if(!$objClass || $objClass.getClass().getName().indexOf('.Class') == -1)
192 #showHeading($appName, $headingShowing)
193
194 {{error}}{{translation key="xe.admin.configurable.configurationClassNonexistant"/}}{{/error}}
195
196 #else
197 ## Use the first object from the document which is of the configuration class.
198 #set($obj = $app.getObject($objClass.getName()))
199 ##
200 #if(!$obj || $obj.getClass().getName().indexOf('.Object') == -1)
201 #showHeading($appName, $headingShowing)
202
203 {{error}}
204 #set($escapedObjClassName =
205 $services.rendering.escape($escapetool.java($objClass.getName()), 'xwiki/2.1'))
206 #set($translationEscapedAppName =
207 $services.rendering.escape($escapetool.java($app.getFullName()), 'xwiki/2.1'))
208 {{translation key="xe.admin.configurable.noObjectOfConfigurationClassFound"
209 parameters="~"$escapedObjClassName~", ~"$translationEscapedAppName~""/}}
210 {{/error}}
211
212 #else
213 ##
214 ## Merge save buttons, remove headings from subsections, and make information links into popups.
215 ## This is not done if there is only a custom defined form.
216 $xwiki.jsx.use($nameOfThisDocument)##
217 ##
218 ## We don't begin the form until we have content for it so that a configurable can specify a
219 ## custom form in codeToExecute and if that configurable object is the first of it's kind in that
220 ## document, the custom form will not be put inside of our form.
221 #if(!$insideForm)
222 ## We are opening a form and fieldset without closing it, thus we cannot clean this html.
223
224 {{html clean=false}}
225 <form id="$formId" method="post" action="$formAction" class="xform">
226 <fieldset>
227 {{/html}}
228 #set($insideForm = true)
229 #end
230
231 {{html}}
232 $formHtml.toString()
233 {{/html}}
234 #end## If object exists
235 #end## If class exists
236 #end## If class name is specified.
237 #end## Foreach configurable object found in this document
238 ## If a form was started then we end it.
239 #if($insideForm)
240
241 ## This is closing an open form which was opened above, we cannot clean this html.
242 {{html clean=false}}
243 ## We add in a redirect field to prevent the user from being carried away when they save
244 ## if they don't have javascript.
245 #set($thisURL = $request.getRequestURL())
246 #if($request.getQueryString() && $request.getQueryString().length() > 0)
247 #set($thisURL = "${thisURL}?$request.getQueryString()")
248 #end
249 <input type="hidden" id="${escapedAppName}_redirect" name="$redirectParameter" value="$escapetool.xml($thisURL)" />
250 <input type="hidden" name="form_token" value="$!{services.csrf.getToken()}" />
251 </fieldset>
252 <div class="bottombuttons">
253 <p class="admin-buttons">
254 <span class="buttonwrapper">
255 ## Text to display on the button. If there is a heading then this button should be labeled
256 ## that it is for saving this section. Otherwise it should be a generic "save" button.
257 #if($headingShowing)
258 #set($buttonText = "$services.localization.render('admin.save') $escapedAppName")
259 #else
260 #set($buttonText = "$services.localization.render('admin.save')")
261 #end
262 <input class="button" type="submit" name="action_saveandcontinue" value="$buttonText" />
263 </span>
264 </p>
265 </div> ## bottombuttons
266 </form>
267 #set($insideForm = false)
268 {{/html}}
269 #end
270 #end## If there are configurable objects
271 #end## If document is not locked or forceEdit is enabled
272 #end## Foreach document name in names to configure
273
274 {{html}}
275 <script>
276 /* <![CDATA[ */
277 ## Alt+Shift+S presses the first saveAndContinue button it finds, not what we want so we will disable edit shortcuts.
278 document.observe('xwiki:dom:loaded', function() {
279 XWiki.actionButtons.EditActions = Object.extend(XWiki.actionButtons.EditActions, {addShortcuts : function() { }});
280 });
281 //]]>
282 </script>
283 {{/html}}##
284 ##
285 #elseif ($currentDoc != 'XWiki.ConfigurableClass')
286 ##
287 ##------------------------------------------------------------------------------------------------------------
288 ## If section is not set then we are viewing the main administration page.
289 ##------------------------------------------------------------------------------------------------------------
290 ##
291 ## If there is no list called sections then we set sections to an empty list.
292 #if(!$sections || $sections.getClass().getName().indexOf('List') == -1)
293 #set($sections = [])
294 #end
295 ##
296 ## We have to create a list of documents which the current user doesn't have permission to view.
297 ## So we can add an error message to the bottom of the page if there are any.
298 #set($appsUserCannotView = [])
299 ##
300 ## A list of sections (to be added) which the user is not allowed to edit, icons will be displayed with a message
301 #set($sectionsUserCannotEdit = [])
302 ## List of sections to be added, in order by creationDate of oldest contained application.
303 #set($sectionsToAdd = [])
304 ## Map of URL of icon to use by the name of the section to use that icon on.
305 #set($iconBySection = {})
306 ##
307 #set($outputList = [])
308 #findNamesOfAppsToConfigure("", $globaladmin, $currentSpace, $outputList)
309 ##
310 #foreach($appName in $outputList)
311 ##
312 ## Get the configurable application
313 #set($app = $xwiki.getDocument($appName))
314 ##
315 ## If getDocument returns null, then warn the user that they don't have view access to that application.
316 #if(!$app)
317 #set($discard = $appsUserCannotView.add($appName))
318 #end
319 ##
320 #set($configurableObjects = $app.getObjects($nameOfThisDocument))
321 #foreach($configurableObject in $configurableObjects)
322 #set($displayInSection = $app.getValue('displayInSection', $configurableObject))
323 ##
324 ## If there is no section for this configurable or if the section cannot be edited, then check if the
325 ## application can be edited by the current user, if so then we display the icon from the current app and
326 ## don't display any message to tell the user they can't edit that section.
327 #if(!$sections.contains($displayInSection) || $sectionsUserCannotEdit.contains($displayInSection))
328 ##
329 ## If there is no section for this configurable, then we will have to add one.
330 #if(!$sections.contains($displayInSection) && !$sectionsToAdd.contains($displayInSection))
331 #set($discard = $sectionsToAdd.add($displayInSection))
332 #end
333 ##
334 ## If an attachment by the filename iconAttachment exists and is an image
335 #set($attachment = $app.getAttachment("$app.getValue('iconAttachment', $configurableObject)"))
336 #if($attachment && $attachment.isImage())
337 ## Set the icon for this section as the attachment URL.
338 #set($discard = $iconBySection.put($displayInSection, $app.getAttachmentURL($attachment.getFilename())))
339 #end
340 ##
341 ## If the user doesn't have edit access to the application, we want to show a message on the icon
342 #if(!$xcontext.hasAccessLevel("edit", $app.getFullName()))
343 #if(!$sectionsUserCannotEdit.contains($displayInSection))
344 #set($discard = $sectionsUserCannotEdit.add($displayInSection))
345 #end
346 #elseif($sectionsUserCannotEdit.contains($displayInSection))
347 ## If the user didn't have access to the section before but does have access to _this_ app which is
348 ## configured in the section, then the section becomes accessible.
349 #set($discard = $sectionsUserCannotEdit.remove($displayInSection))
350 #end
351 #end## If section doesn't exist or user doesn't have access.
352 #end## Foreach configurable object in this app.
353 #end## Foreach application which is configurable.
354 ##
355 ## Now we go through sectionsToAdd and generate icons for them
356 #set($defaultIcon = $xwiki.getAttachmentURL($nameOfThisDocument, 'DefaultAdminSectionIcon.png'))
357 #if($globaladmin)
358 #set($queryString = "editor=globaladmin&amp;section=")
359 #else
360 #set($queryString = "space=$escapetool.url($currentSpace)&amp;section=")
361 #if($request.getParameter('editor'))
362 #set($queryString = "editor=$escapetool.url($request.getParameter('editor'))&amp;$queryString")
363 #end
364 #end
365
366 ## This is an html fragment and thus cannot be cleaned
367 {{html clean=false}}
368 #foreach($sectionToAdd in $sectionsToAdd)
369 #set($icon = $iconBySection.get($sectionToAdd))
370 #if(!$icon)
371 #set($icon = $defaultIcon)
372 #end
373 <li class="$escapetool.xml($sectionToAdd).replaceAll(' ', '_')">
374 #set($hasAccess = !$sectionsUserCannotEdit.contains($sectionToAdd))
375 #if($hasAccess)
376 <a href="$xwiki.getURL($currentDoc, $xcontext.getAction(), "$queryString$escapetool.url($sectionToAdd)")">
377 #else
378 <a title="$services.localization.render('xe.admin.configurable.sectionIconNoAccessTooltip')">
379 #end
380 <span>
381 <img src="$icon" alt="$escapetool.xml($sectionToAdd) icon"/>
382 ## Try to translate the names of the sections, build the key by adding an "admin." in front.
383 ## Not the best way to translate, but very inline with the way the translations are done in XWiki.AdminSheet for individual administration page titles.
384 ## If there is no translation (translated message is equals to key), don't display the message key, but the section name instead.
385 #if($services.localization.get("admin.${sectionToAdd.toLowerCase()}"))
386 #set($sectionDisplayName = $services.localization.render("admin.${sectionToAdd.toLowerCase()}"))
387 #else
388 #set($sectionDisplayName = $sectionToAdd)
389 #end
390 $escapetool.xml($sectionDisplayName)
391 </span>
392 #if(!$hasAccess)
393 <br/><span class="errormessage">$services.localization.render('xe.admin.configurable.sectionIconNoAccess')</span>
394 #end
395 </a>
396 </li>
397 #end
398 {{/html}}
399
400 ## Finally we display an error message if there are any applications which we were unable to view.
401 #if($appsUserCannotView.size() > 0)
402 {{error}}$services.localization.render('xe.admin.configurable.noViewAccessSomeApplications',
403 'xwiki/2.1', [$appsUserCannotView]){{/error}}
404
405 #end
406 #end## If we should be looking at the main administration page.
407 {{/velocity}}