Wiki source code of Default Class Sheet

Last modified by Simon Urli on 2023/05/25

Show last authors
1 {{template name="locationPicker_macros.vm" /}}
2
3 {{velocity}}
4 ## This document can be copied in order to be customized so we cannot rely on its name to determine if the currently
5 ## displayed document is a class or the class sheet itself. We look for the sheet descriptor instead.
6 #set ($isSheet = $doc.getObject('XWiki.SheetDescriptorClass'))
7 #if ($isSheet)
8 ## Viewing the sheet document itself.
9 {{translation key="platform.xclass.defaultClassSheet.description"/}}
10 #elseif ("$!request.bindSheet" != '' && $hasEdit)
11 #if ($services.csrf.isTokenValid($request.getParameter('form_token')))
12 ## Bind the sheet to the class.
13 #set ($classSheetReference = $services.model.resolveDocument($request.bindSheet))
14 #if ($services.sheet.bindClassSheet($doc, $classSheetReference))
15 $doc.save($services.localization.render('platform.xclass.defaultClassSheet.sheets.bind'))
16 #end
17 $response.sendRedirect($request.xredirect)
18 #else
19 $response.sendRedirect($services.csrf.getResubmissionURL())
20 #end
21 ## Stop processing, since we already sent a redirect.
22 #stop
23 #elseif("$!request.docName" != '')
24 ## Request for creating a new instance.
25 ## We don't actually create a new instance here, we just redirect to the edit mode.
26 #set ($targetSpaceRef = $services.model.resolveSpace($request.spaceName))
27 #set ($targetDocRef = $services.model.createDocumentReference($request.docName, $targetSpaceRef))
28 #if (!$xwiki.exists($targetDocRef) && $services.security.authorization.hasAccess('edit', $targetDocRef))
29 ## Compute the default edit mode to ensure backward compatibility with documents that are still using the deprecated
30 ## inline action.
31 #set ($editAction = $xwiki.getDocument($request.template).getDefaultEditMode())
32 $response.sendRedirect($xwiki.getURL($targetDocRef, $editAction, $escapetool.url({
33 'form_token': $request.form_token,
34 'template': $request.template,
35 'parent': $request.parent,
36 'title': $request.docName
37 })))
38 ## Stop processing, since we already sent a redirect.
39 #stop
40 #end
41 #end
42 {{/velocity}}
43
44 {{velocity}}
45 ## If this sheet is explicitly bound to the displayed class then print the class document content before the
46 ## sheet output. Class authors can put the description of the class in the class document content.
47 #set($classSheetReference = $services.model.createDocumentReference($doc.wiki, 'XWiki', 'ClassSheet'))
48 #if($services.sheet.getDocumentSheets($doc).contains($classSheetReference))
49 {{include reference="" author="target"/}}
50 #end
51 {{/velocity}}
52
53 {{velocity}}
54 #if (!$isSheet)
55 #set ($className = $doc.pageReference.name)
56 #set ($className = $stringtool.removeEnd($className, 'Class'))
57 ## Determine the class sheets.
58 #set ($classSheetReferences = $services.sheet.getClassSheets($doc))
59 #if ($classSheetReferences.isEmpty())
60 ## There is no class sheet explicitly bound to this class. Fall-back on naming convention.
61 ## Before XWiki 2.0, the default class sheet was suffixed with "ClassSheet". Since 2.0, the suffix is just "Sheet".
62 #set ($defaultClassSheetReference = $services.model.createDocumentReference("${className}ClassSheet",
63 $doc.documentReference.parent))
64 #if (!$xwiki.exists($defaultClassSheetReference))
65 #set ($defaultClassSheetReference = $services.model.createDocumentReference("${className}Sheet",
66 $doc.documentReference.parent))
67 #end
68 #end
69 ## Determine the template using naming convention.
70 ## Before XWiki 2.0, the default class template was suffixed with "ClassTemplate".
71 ## Since 2.0, the suffix is just "Template".
72 #set ($classTemplateReference = $services.model.createDocumentReference("${className}ClassTemplate",
73 $doc.documentReference.parent))
74 #if (!$xwiki.exists($classTemplateReference))
75 #set ($classTemplateReference = $services.model.createDocumentReference("${className}Template",
76 $doc.documentReference.parent))
77 #end
78 ## Determine the template provider using naming convention.
79 #set ($classTemplateProviderReference = $services.model.createDocumentReference("${className}TemplateProvider",
80 $doc.documentReference.parent))
81 #set ($classTemplateProviderDoc = $xwiki.getDocument($classTemplateProviderReference))
82 #set ($hasClassTemplateProvider = !$classTemplateProviderDoc.isNew())
83 #set($classTemplateDoc = $xwiki.getDocument($classTemplateReference))
84 #set($hasClassSheets = !$classSheetReferences.isEmpty() || $xwiki.exists($defaultClassSheetReference))
85 #set($hasClassTemplate = !$classTemplateDoc.isNew())
86 #if(!$defaultSpace)
87 #set($defaultSpace = $doc.space)
88 #end
89 #if(!$defaultParent)
90 #set($defaultParent = ${doc.fullName})
91 #end
92
93 #set ($classEditorURL = $doc.getURL('edit', 'editor=class'))
94 #if($doc.getxWikiClass().properties.size() == 0)
95 #set ($openLink = "<a href='$escapetool.xml($classEditorURL)'>")
96 #set ($closeLink = '</a>')
97 {{warning}}
98 {{html}}
99 ## First escape the content of the translation, then replace the placeholders with content that would otherwise be
100 ## escaped during the first escaping.
101 #set ($warningMessage = $services.localization.render('platform.xclass.defaultClassSheet.properties.empty',
102 ['__OPEN_LINK__', '__CLOSE_LINK__']))
103 $escapetool.xml($warningMessage).replace('__OPEN_LINK__', $openLink).replace('__CLOSE_LINK__', $closeLink)
104 {{/html}}
105 {{/warning}}
106 #else
107 (% id="HClassProperties" %)
108 = {{translation key="platform.xclass.defaultClassSheet.properties.heading"/}} =
109 #foreach($property in $doc.getxWikiClass().properties)
110 * $services.rendering.escape("$property.prettyName ($property.name: $xwiki.metaclass.get($property.classType).prettyName)", $xwiki.currentContentSyntaxId)
111 #end
112 #set ($openLink = "<a href='$escapetool.xml($classEditorURL)'>")
113 #set ($closeLink = '</a>')
114 #set ($warningMessage = $escapetool.xml($services.localization.render('platform.xclass.defaultClassSheet.properties.edit', ['__OPEN_LINK__', '__CLOSE_LINK__'])))
115 ## First escape the content of the translation, then replace the placeholders with content that would otherwise be
116 ## escaped during the first escaping.
117 * //{{html}}$warningMessage.replace('__OPEN_LINK__', $openLink).replace('__CLOSE_LINK__', $closeLink){{/html}}//
118
119 #end
120 #if ($hasClassSheets && $hasClassTemplate)
121 (% id="HCreatePage" %)
122 = {{translation key="platform.xclass.defaultClassSheet.createPage.heading"/}} =
123 #if("$!targetDocRef" != '' && $xwiki.exists($targetDocRef))
124 {{warning}}
125 {{html}}
126 #set ($targetDocLink = $xwiki.getURL($targetDocRef))
127 #set ($openLink = "<a href='$escapetool.xml($targetDocLink)'>")
128 #set ($message = $escapetool.xml($services.localization.render('platform.xclass.defaultClassSheet.createPage.pageAlreadyExists', ['__OPEN_LINK__', '__CLOSE_LINK__'])))
129 ## First escape the content of the translation, then replace the placeholders with content that would
130 ## otherwise be escaped during the first escaping.
131 $message.replace('__OPEN_LINK__', $openLink).replace('__CLOSE_LINK__', '</a>')
132 {{/html}}
133 {{/warning}}
134 #elseif("$!targetDocRef" != '')
135
136 {{warning}}{{translation key="platform.xclass.defaultClassSheet.createPage.denied"/}}{{/warning}}
137 #end
138
139 {{html}}
140 <form action="$doc.getURL()" id="newdoc" method="post" class="xform half">
141 <fieldset>
142 <div class="hidden">
143 <input type="hidden" name="form_token" value="$!{services.csrf.getToken()}" />
144 <input type="hidden" name="parent" value="$escapetool.xml(${defaultParent})"/>
145 <input type="hidden" name="template" value="$escapetool.xml(${classTemplateDoc})"/>
146 <input type="hidden" name="sheet" value="1"/>
147 </div>
148 #locationPicker({
149 'id': 'target',
150 'title': {
151 'label': 'core.create.title',
152 'hint': 'core.create.title.hint',
153 'name': 'docTitle',
154 'placeholder': 'core.create.name.placeholder'
155 },
156 'preview': {
157 'label': 'core.create.locationPreview.label',
158 'hint': 'core.create.locationPreview.hint'
159 },
160 'parent': {
161 'label': 'core.create.spaceReference.label',
162 'hint': 'core.create.spaceReference.hint',
163 'name': 'spaceName',
164 'reference': $services.model.resolveSpace($defaultSpace),
165 'placeholder': 'core.create.spaceReference.placeholder'
166 },
167 'name': {
168 'label': 'core.create.name.label',
169 'hint': 'core.create.name.hint',
170 'name': 'docName',
171 'placeholder': 'core.create.name.placeholder'
172 }
173 })
174 <p>
175 <span class="buttonwrapper">
176 <input type="submit" class="button" value="$escapetool.xml($services.localization.render(
177 'platform.xclass.defaultClassSheet.createPage.label'))"/>
178 </span>
179 </p>
180 </fieldset>
181 </form>
182 {{/html}}
183
184 #end## has class sheet and class template
185 (% id="HExistingPages" %)
186 = {{translation key="platform.xclass.defaultClassSheet.pages.heading"/}} =
187
188 {{translation key="platform.xclass.defaultClassSheet.pages.description"/}}
189
190 #set ($options = {
191 'className': $doc.fullName,
192 'translationPrefix' : 'platform.index.',
193 'queryFilters': ['unique']
194 })
195 {{liveData
196 id="classEntries"
197 properties="doc.title,doc.location,doc.date,doc.author,doc.objectCount,_actions"
198 source="liveTable"
199 className="$services.rendering.escape(${doc.fullName}, 'xwiki/2.1')"
200 sourceParameters="$services.rendering.escape($escapetool.url($options), 'xwiki/2.1')"
201 }}
202 {
203 "meta": {
204 "propertyDescriptors": [
205 {
206 "id": "doc.title",
207 "editable": false
208 },
209 {
210 "id": "doc.objectCount",
211 "editable": false,
212 "filterable": false,
213 "sortable": false
214 }
215 ]
216 }
217 }
218 {{/liveData}}
219
220 (% id="HClassSheets" %)
221 = {{translation key="platform.xclass.defaultClassSheet.sheets.heading"/}} =
222 #if (!$hasClassSheets || !$hasClassTemplate)
223
224 {{translation key="platform.xclass.defaultClassSheet.sheets.missing"/}}
225 #end
226
227 {{info}}
228 #set ($message = $services.localization.render('platform.xclass.defaultClassSheet.sheets.description', ['__START_EM__', '__END_EM__']))
229 #set ($message = $escapetool.xml($message))
230 ## First escape the content of the translation, then replace the placeholders with content that would
231 ## otherwise be escaped during the first escaping.
232 {{html}}$message.replace('__START_EM__', '<em>').replace('__END_EM__', '</em>'){{/html}}
233 {{/info}}
234
235 #if(!$hasClassSheets)
236 {{html}}
237 <form action="$xwiki.getURL($defaultClassSheetReference, 'save', 'editor=wiki')" method="post">
238 <div>
239 <input type="hidden" name="form_token" value="$!{services.csrf.getToken()}" />
240 <input type="hidden" name="parent" value="$escapetool.xml(${doc.fullName})"/>
241 <input type="hidden" name="xredirect" value="$escapetool.xml(${doc.URL})"/>
242 #set ($sheetContent = $xwiki.getDocument('XWiki.ObjectSheet').getContent().replace('XWiki.MyClass',
243 $doc.fullName))
244 ## We have to encode the new line characters in order to preserve them, otherwise they are replace with a
245 ## space when the HTML is cleaned.
246 ## FIXME: Use a dedicated escape tool method when XCOMMONS-405 is implemented.
247 #set ($sheetContent = $escapetool.xml($sheetContent).replaceAll("\n", '&#10;'))
248 <input type="hidden" name="content" value="$sheetContent"/>
249 <input type="hidden" name="title" value="${escapetool.h}if(${escapetool.d}doc.documentReference.name == '$escapetool.xml($defaultClassSheetReference.name)')$escapetool.xml($className) Sheet${escapetool.h}{else}${escapetool.d}services.display.title(${escapetool.d}doc, {'displayerHint': 'default', 'outputSyntaxId': 'plain/1.0'})${escapetool.h}end"/>
250 <span class="buttonwrapper"><input type="submit" class="button" value="$escapetool.xml(
251 $services.localization.render('platform.xclass.defaultClassSheet.sheets.create'))"/></span>
252 </div>
253 </form>
254 {{/html}}
255 #else
256 #set($defaultClassSheetDoc = $xwiki.getDocument($defaultClassSheetReference))
257 #if($classSheetReferences.isEmpty() && !$defaultClassSheetDoc.getObject('XWiki.SheetClass'))
258 ## The sheet is not bound to the class.
259 #set($xredirect = $xwiki.relativeRequestURL)
260 #set($defaultClassSheetStringReference = $services.model.serialize($defaultClassSheetReference, "default"))
261 #set($bindURL = $doc.getURL('view', "bindSheet=${escapetool.url($defaultClassSheetStringReference)}&xredirect=${escapetool.url($xredirect)}&form_token=$!{services.csrf.getToken()}"))
262 {{warning}}
263 {{translation key="platform.xclass.defaultClassSheet.sheets.notBound"/}} ##
264 #if ($hasEdit)
265 {{html}}
266 <a href="$escapetool.xml($bindURL)">##
267 $escapetool.xml($services.localization.render('platform.xclass.defaultClassSheet.sheets.bind')) »##
268 </a>.
269 {{/html}}
270 #end
271 {{/warning}}
272
273 #end
274 #if ($classSheetReferences.size() < 2)
275 #set($classSheetDoc = $defaultClassSheetDoc)
276 #if(!$classSheetReferences.isEmpty())
277 #set($classSheetDoc = $xwiki.getDocument($classSheetReferences.get(0)))
278 #end
279 #set ($sheetPath = "#hierarchy($classSheetDoc.documentReference, {'plain': true, 'local': true, 'limit': 4})")
280 #set ($classSheetLink = "$services.localization.render('platform.xclass.defaultClassSheet.sheets.view', [$sheetPath.trim()]) »")
281 #set ($classSheetLink = $services.rendering.escape($classSheetLink, 'xwiki/2.1'))
282 #set ($classSheetLink = $services.rendering.escape($classSheetLink, 'xwiki/2.1'))
283 #set ($classSheetText = ${classSheetDoc.fullName})
284 #set ($classSheetText = $services.rendering.escape($classSheetText, 'xwiki/2.1'))
285 [[$classSheetLink>>$classSheetText]]
286 #else
287 {{translation key="platform.xclass.defaultClassSheet.sheets.list"/}}
288
289 #foreach($classSheetReference in $classSheetReferences)
290 * [[$services.model.serialize($classSheetReference, "default")]]
291 #end
292 #end
293 #end
294
295 (% id="HClassTemplate" %)
296 = {{translation key="platform.xclass.defaultClassSheet.template.heading"/}} =
297
298 {{info}}
299 #set ($message = $services.localization.render('platform.xclass.defaultClassSheet.template.description', ['__START_EM__', '__END_EM__']))
300 #set ($message = $escapetool.xml($message))
301 ## First escape the content of the translation, then replace the placeholders with content that would
302 ## otherwise be escaped during the first escaping.
303 {{html}}$message.replace('__START_EM__', '<em>').replace('__END_EM__', '</em>'){{/html}}
304 {{/info}}
305
306 #if (!$hasClassTemplate)
307 {{html}}
308 <form action="$escapetool.xml($classTemplateDoc.getURL('save', 'editor=wiki'))" method="post">
309 <div>
310 <input type="hidden" name="form_token" value="$!{services.csrf.getToken()}" />
311 <input type="hidden" name="parent" value="$escapetool.xml(${doc.fullName})"/>
312 <input type="hidden" name="xredirect" value="$escapetool.xml(${doc.URL})"/>
313 <input type="hidden" name="title" value="$escapetool.xml($className) Template"/>
314 <span class="buttonwrapper"><input type="submit" class="button" value="$escapetool.xml(
315 $services.localization.render('platform.xclass.defaultClassSheet.template.create'))"/></span>
316 </div>
317 </form>
318 {{/html}}
319 #else
320 #if(!$classTemplateDoc.getObject(${doc.fullName}))
321 #set($xredirect = $xwiki.relativeRequestURL)
322 #set($createUrl = $classTemplateDoc.getURL('objectadd', "classname=${escapetool.url($doc.fullName)}&xredirect=${escapetool.url($xredirect)}&form_token=$!{services.csrf.getToken()}"))
323 {{warning}}
324 #set ($message = $services.localization.render('platform.xclass.defaultClassSheet.template.missingObject', ['__CLASS_NAME__']))
325 #set ($message = $escapetool.xml($message))
326 {{html}}
327 ## First escape the content of the translation, then replace the placeholders with content that would
328 ## otherwise be escaped during the first escaping.
329 $message.replace('__CLASS_NAME__', "<em>$escapetool.xml($className)</em>")
330 <a href="$escapetool.xml($createUrl)">##
331 $escapetool.xml($services.localization.render('platform.xclass.defaultClassSheet.template.addObject', [$className])) »##
332 </a>.
333 {{/html}}
334 {{/warning}}
335
336 #end
337 #set ($templatePath = "#hierarchy($classTemplateDoc.documentReference, {'plain': true, 'local': true, 'limit': 4})")
338 #set ($templateDocLink = "$services.localization.render('platform.xclass.defaultClassSheet.template.view', [$templatePath.trim()]) »")
339 #set ($templateDocLink = $services.rendering.escape($templateDocLink, 'xwiki/2.1'))
340 #set ($templateDocLink = $services.rendering.escape($templateDocLink, 'xwiki/2.1'))
341 #set ($templateDocText = "${classTemplateDoc.fullName}")
342 ## First escape the xwiki/2.1 syntax of the translation, then replace the placeholders with content that would
343 ## otherwise be escaped during the first escaping.
344 #set ($templateDocText = $services.rendering.escape($templateDocText, 'xwiki/2.1'))
345 [[$templateDocLink>>$templateDocText]]
346 #end
347 ## Create a template provider only if a template for the current class exists.
348 #if ($classTemplateDoc.getObject(${doc.fullName}))
349 (% id="HClassTemplateProvider" %)
350 = {{translation key="platform.xclass.defaultClassSheet.templateProvider.heading"/}} =
351
352 {{info}}
353 #set ($message = $services.localization.render('platform.xclass.defaultClassSheet.templateProvider.description', ['__EM__']))
354 #set ($message = $services.rendering.escape($message, 'xwiki/2.1'))
355 ## First escape the xwiki/2.1 syntax of the translation, then replace the placeholders with content that would
356 ## otherwise be escaped during the first escaping.
357 ## The replacement key is itself escaped, and it's escaped form needs to be used for the replacement.
358 $message.replace('~_~_~E~M~_~_', '//')
359 {{/info}}
360
361 #if (!$hasClassTemplateProvider)
362 #set ($templateProviderClassName = 'XWiki.TemplateProviderClass')
363 ## Do the page creation and object addition in one step, providing some default values.
364 ## In order to get the root space of the class and use it as restrictionSpace, we need to be sure that we have
365 ## the expected result for multiple level hierarchies, like MyApplication.Code.MyApplicationClass. In this case,
366 ## the template provider in enabled in MyApplication space.
367 #set ($restrictionSpace = $doc.documentReference.spaceReferences.get(0).name)
368 #set ($createUrlQueryString = $escapetool.url({
369 'classname': $templateProviderClassName,
370 'xredirect': $xwiki.relativeRequestURL,
371 'form_token': $services.csrf.token,
372 "${templateProviderClassName}_name": $className,
373 "${templateProviderClassName}_description":
374 $services.localization.render('platform.xclass.templateProvider.defaultDescription', [$className]),
375 "${templateProviderClassName}_template": $classTemplateDoc,
376 "${templateProviderClassName}_visibilityRestrictions": $restrictionSpace}))
377 #set ($createUrl = $classTemplateProviderDoc.getURL('objectadd', $createUrlQueryString))
378 {{html}}
379 <form action="$escapetool.xml($classTemplateProviderDoc.getURL('save', 'editor=wiki'))" method="post">
380 <div>
381 <input type="hidden" name="form_token" value="$!{services.csrf.getToken()}" />
382 <input type="hidden" name="parent" value="$escapetool.xml(${doc.fullName})"/>
383 <input type="hidden" name="xredirect" value="$escapetool.xml($createUrl)"/>
384 <input type="hidden" name="title" value="$escapetool.xml($className) Template Provider"/>
385 <span class="buttonwrapper"><input type="submit" class="button" value="$escapetool.xml(
386 $services.localization.render('platform.xclass.defaultClassSheet.templateProvider.create'))"/></span>
387 </div>
388 </form>
389 {{/html}}
390 #else
391 #set ($templateProviderPath = "#hierarchy($classTemplateProviderDoc.documentReference, {'plain': true, 'local': true, 'limit': 4})")
392 #set ($linkTarget = "$services.localization.render('platform.xclass.defaultClassSheet.templateProvider.view', [$templateProviderPath.trim()]) »")
393 #set ($linkTarget = $services.rendering.escape($linkTarget, 'xwiki/2.1'))
394 #set ($linkTarget = $services.rendering.escape($linkTarget, 'xwiki/2.1'))
395 #set ($linkLabel = $services.rendering.escape(${classTemplateProviderDoc.fullName}, 'xwiki/2.1'))
396 [[$linkTarget>>$linkLabel]]
397 #end
398 #end
399
400 #end## !$isSheet
401 {{/velocity}}

Get Connected