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