Wiki source code of Attachments

Last modified by shahzad kazama on 2023/12/18 18:56

Show last authors
1 {{velocity output="false"}}
2 #set ($translationPrefix = 'xe.attachmentSelector')
3
4 #if ($request.xaction == 'postUpload')
5 #set ($targetDocument = $xwiki.getDocument($request.get('docname')))
6 #set ($targetAttachDocument = $xwiki.getDocument($request.get('targetdocname')))
7
8 #set ($fieldname = $request.get('fieldname'))
9 #set ($comment = $services.localization.render("${translationPrefix}.postUpload.comment", [$fieldname]))
10 #set ($docAction = $request.get('docAction'))
11 #set ($attachmentList = $targetAttachDocument.getAttachmentList())
12 #if ($attachmentList && $attachmentList.size() > 0)
13 #set ($sortedAttachments = $collectiontool.sort($attachmentList, 'date:desc'))
14 #set ($lastAttachment = $sortedAttachments.get(0))
15 #end
16 $response.sendRedirect($targetDocument.getURL($docAction, $escapetool.url({
17 $fieldname: $lastAttachment.filename,
18 'comment': $comment,
19 'form_token': $request.form_token
20 })))
21 #stop
22 #end
23 {{/velocity}}
24
25 {{velocity output="false"}}
26 ##
27 ## Macros
28 ##
29 #set ($attachmentPickerDocName = 'XWiki.AttachmentSelector')
30
31 $xwiki.ssx.use($attachmentPickerDocName)
32 $xwiki.jsx.use($attachmentPickerDocName)
33
34 #**
35 * Displays the attachment gallery as a list of attachment boxes, starting with special boxes for uploading a new attachment and for setting a default value.
36 *
37 * @param $targetDocument the document to recieve the field value being modified
38 * @param $targetAttachDocument the document to list/save attachments to
39 * @param $options generic picker options
40 *#
41 #macro (attachmentPicker_displayAttachmentGallery $targetDocument, $targetAttachDocument, $options)
42 #set ($currentValue = $targetDocument.getValue($options.property))
43 #if ("$!{targetAttachDocument.getAttachment($currentValue)}" == '')
44 #set ($currentValue = "$!{options.defaultValue}")
45 #end
46 (% class="gallery" %)(((
47 ## Only display the upload form if they have edit permission on targetAttachDocument
48 #attachmentPicker_displayUploadForm($targetDocument, $targetAttachDocument, $options)
49 #attachmentPicker_displayAttachmentGalleryEmptyValue($targetDocument, $targetAttachDocument, $options, $currentValue)
50 #if ("$!services.temporaryAttachments" != '')
51 #set ($unsortedAttachments = $services.temporaryAttachments.listAllAttachments($targetAttachDocument))
52 #set ($sortedAttachments = $collectiontool.sort($unsortedAttachments, "${options.sortAttachmentsBy}"))
53 #else
54 #set ($sortedAttachments = $collectiontool.sort($targetAttachDocument.getAttachmentList(), "${options.sortAttachmentsBy}") )
55 #end
56 #foreach ($attachment in $sortedAttachments)
57 #set ($extension = $attachment.getFilename())
58 #set ($extension = $extension.substring($mathtool.add($extension.lastIndexOf('.'), 1)).toLowerCase())
59 #if ($options.filter.size() == 0 || $options.filter.contains($extension))
60 #attachmentPicker_displayAttachmentBox($attachment $targetDocument $targetAttachDocument, $options $currentValue)
61 #end
62 #end
63 )))
64 #end
65
66 #**
67 * Displays an attachment box.
68 *
69 * @param $attachment the target attachment to display
70 * @param $targetDocument the document being modified
71 * @param $options generic picker options
72 * @param $currentValue the currently selected file, used for determining if the box should be highlighted as the current value
73 *#
74 #macro (attachmentPicker_displayAttachmentBox $attachment $targetDocument $targetAttachDocument, $options $currentValue)
75 #set ($hasTemporaryAttachment = "$!services.temporaryAttachments" != '')
76 #set ($canEdit = $xwiki.hasAccessLevel('edit', $xcontext.user, ${targetAttachDocument.fullName}))
77 #set ($isTemporaryAttachment = false)
78 #if(!$hasTemporaryAttachment)
79 #set ($canDeleteAttachment = $canEdit)
80 #else
81 #set ($isTemporaryAttachment = $services.temporaryAttachments.temporaryAttachmentExists($attachment))
82 ## TODO: Update once it is made possible to delete temporary attachments (see XWIKI-20225).
83 #set ($canDeleteAttachment = !$isTemporaryAttachment && $canEdit)
84 #end
85 #set ($cssClasses = [])
86 #if ($options.displayImage && $attachment.isImage())
87 #set ($discard = $cssClasses.add('gallery_image'))
88 #end
89 #if ($isTemporaryAttachment)
90 #set ($discard = $cssClasses.add('temporary_attachment'))
91 #end
92 #attachmentPicker_displayStartFrame({'value' : $attachment.filename, 'text' : $attachment.filename, 'cssClass' : "${stringtool.join($cssClasses, ' ')}"} $currentValue)
93 #attachmentPicker_displayAttachmentDetails($attachment $options)
94 #set ($returnURL = $escapetool.url($doc.getURL('view', $request.queryString)))
95 #set ($deleteURL = $targetAttachDocument.getAttachmentURL($attachment.filename, 'delattachment', "xredirect=${returnURL}&form_token=$!{services.csrf.getToken()}") )
96 #set ($viewURL = $targetAttachDocument.getAttachmentURL($attachment.filename) )##{'name' : 'download', 'url' : $viewURL, 'rel' : '__blank'}
97 #set ($selectURL = $targetDocument.getURL(${options.get('docAction')}, $escapetool.url({
98 "${options.get('classname')}_${options.get('object')}_${options.get('property')}": ${attachment.filename},
99 'form_token': $!{services.csrf.getToken()}
100 })))
101 ## Delete action is only proposed for users with the edit right on the document.
102 ## If the temporary attachment is available, the delete action is only allowed for non-temporary attachments.
103 #set ($attachmentActions = [{'name' : 'select', 'url' : $selectURL}])
104 #if($canDeleteAttachment)
105 #set ($discard = $attachmentActions.add({'name' : 'delete', 'url' : $deleteURL}))
106 #end
107 #define($additionalContent)
108 #if ($isTemporaryAttachment)
109 #set ($titleMessage = $services.localization.render('attachment.attachmentSelector.attachmentBox.temporaryAttachmentTitle'))
110 #set ($titleMessage = $services.rendering.escape($titleMessage, 'xwiki/2.1'))
111 (% title="$titleMessage" %)$services.icon.render('clock')(%%)
112 #end
113 #end
114 #attachmentPicker_displayEndFrame ($attachmentActions $additionalContent)
115 #end
116
117 #**
118 * Writes the wiki code used at the start of an attachment box. Outputs the attachment title bar, and opens the inner frame div.
119 *
120 * @param $boxOptions a map of parameters/options for the current attachment, holding, for example, the attachment name (boxOptions.value),
121 * the title to display (boxOptions.text), optional extra CSS classnames to put on the box (boxOptions.cssClass)
122 * @param $currentValue the currently selected file, used for determining if this attachment should be highlighted as the current value
123 *#
124 #macro (attachmentPicker_displayStartFrame $boxOptions $currentValue)
125 (% class="gallery_attachmentbox $!{boxOptions.cssClass} #if ("$!{boxOptions.value}" == $currentValue) current#{end}" %)(((
126 (% class="gallery_attachmenttitle" title="$services.rendering.escape($!{boxOptions.value}, 'xwiki/2.1')" %)(((
127 $services.rendering.escape($boxOptions.text, 'xwiki/2.1')
128 )))
129 (% class="gallery_attachmentframe" %)(((
130 #end
131
132 #**
133 * Displays details about an attachment inside the attachment box. If the attachment is an image and the "displayImage" option is on,
134 * then the image is displayed. Otherwise, some basic information is displayed: the version, the size, the date and the author.
135 *
136 * @param $attachment the target attachment to display
137 * @param $options generic picker options
138 *#
139 #macro (attachmentPicker_displayAttachmentDetails $attachment $options)
140 #if ($attachment)
141 ## Compute the attachment reference because there's no getter.
142 #set ($attachmentReference = $services.model.createAttachmentReference($attachment.document.documentReference,
143 $attachment.filename))
144 #set ($attachmentStringReference = $services.rendering.escape($services.model.serialize($attachmentReference, 'default'), 'xwiki/2.1'))
145 #if ($attachment.isImage() && $options.displayImage)
146 ## We add the version to the query string in order to invalidate the cache when an image attachment is replaced.
147 #set ($queryString = $escapetool.url({'version': $attachment.version}))
148 [[[[image:${attachmentStringReference}||width=180 queryString="$queryString"]]>>attach:$attachmentStringReference]]
149 #else
150 * (% class="mime" %){{html wiki=false clean=false}}#mimetypeimg($attachment.getMimeType().toLowerCase() $attachment.getFilename().toLowerCase()){{/html}}(%%) (% class="filename" %)$services.rendering.escape($attachment.getFilename(), 'xwiki/2.1')(% %)
151 * v$attachment.getVersion() (#dynamicsize($attachment.longSize))
152 * $services.localization.render('core.viewers.attachments.author', [$!{xwiki.getUserName($attachment.author, false)}]) $services.localization.render('core.viewers.attachments.date', [$!{xwiki.formatDate($attachment.date, 'dd/MM/yyyy hh:mm')}])
153 * (% class="buttonwrapper" %)[[${services.localization.render("${translationPrefix}.actions.download")}>>attach:${attachmentStringReference}||title="$services.localization.render("${translationPrefix}.actions.download")" rel="__blank" class="button"]](%%)
154 #end
155 #end
156 #end
157
158 #**
159 * Writes the wiki code used at the end of an attachment box. Closes the inner frame div, and outputs the attachment actions.
160 *
161 * @param $actions a list of maps defining action buttons, where each entry contains a subset of the following:
162 * <dl>
163 * <dt>name</dt>
164 * <dd>identifies the action; the name is used as a CSS classname, and in the translation key for the display text, as "xe.attachmentSelector.actions.<name>"</dd>
165 * <dt>url</dt>
166 * <dd>the destination of the button</dd>
167 * <dt>rel</dt>
168 * <dd>an optional parameter to be used in the "rel" HTML attribute; for example "__blank" can be used to open the link in a new tab/window</dd>
169 * </dl>
170 * @param $additionalContent optional additional content that does not follow the structure of the actions
171 *#
172 #macro (attachmentPicker_displayEndFrame $actions $additionalContent)
173 )))## attachmentframe
174 (% class="gallery_actions" %)(((
175 #foreach ($action in $actions)
176 #set( $actionname = $services.localization.render("${translationPrefix}.actions.${action.name}") )
177 [[${actionname}>>path:${action.url}||class="tool ${action.name}" title="${actionname}" #if($action.rel) rel="${action.rel}"#end]]##
178 #end
179 $!additionalContent
180 )))## actions
181 )))## attachmentbox
182 #end
183
184 #**
185 * Displays the upload box used for adding and selecting a new attachment.
186 *
187 * @param $targetDocument the document with the property being modified
188 * @param $targetAttachDocument the document to upload the attachment to
189 * @param $options generic picker options
190 *#
191 #macro (attachmentPicker_displayUploadForm $targetDocument, $targetAttachDocument, $options)
192 #attachmentPicker_displayStartFrame({
193 'value' : $services.localization.render("${translationPrefix}.upload.title"),
194 'text' : $services.localization.render("${translationPrefix}.upload.title"),
195 'cssClass' : 'gallery_upload'
196 } $NULL)
197 {{html clean="false"}}
198 <form action="$targetAttachDocument.getURL('upload')" enctype="multipart/form-data" method="post" id="uploadAttachment" class="uploadAttachment xform">
199 <div class="gallery_upload_input">
200 #if (${options.rawfilter} != '')
201 <span class="xHint">$escapetool.xml($services.localization.render("${translationPrefix}.upload.hint", [${options.rawfilter}]))</span>
202 #end
203 <input type="file" name="filepath" id="attachfile" class="noitems" title="$!{escapetool.xml($options.rawfilter)}"/>
204 <input type="hidden" name="xredirect" value="$xwiki.getDocument($attachmentPickerDocName).getURL('get', "xaction=postUpload&amp;docAction=$!{escapetool.url($options.get('docAction'))}&amp;targetdocname=$!{escapetool.url($targetAttachDocument.fullName)}&amp;docname=$!{escapetool.url($targetDocument.fullName)}&amp;fieldname=$!{escapetool.url($options.get('classname'))}_$!{escapetool.url($options.get('object'))}_$!{escapetool.url($options.get('property'))}&amp;form_token=$!{services.csrf.getToken()}")" />
205 <input type="hidden" name="docname" value="$!{escapetool.xml($targetDocument.fullName)}" />
206 <input type="hidden" name="classname" value="$!{escapetool.xml($options.get('classname'))}" />
207 <input type="hidden" name="object" value="$!{escapetool.xml($options.get('object'))}" />
208 <input type="hidden" name="property" value="$!{escapetool.xml($options.get('property'))}" />
209 <input type="hidden" name="form_token" value="$!{services.csrf.getToken()}" />
210 </div>
211 #if ("$!currentValue" != '' && $currentValue != $options.defaultValue)
212 <div>
213 <label>
214 <input type="checkbox" name="filename" value="$!escapetool.xml($currentValue)"
215 />$services.localization.render('attachmentSelector.replace',
216 ["<strong>$!escapetool.xml($currentValue)</strong>"])
217 </label>
218 <span class="xHint">$escapetool.xml($services.localization.render('attachmentSelector.replace.hint'))</span>
219 </div>
220 #end
221 #if ($xwiki.hasEditComment() && $options.versionSummary)
222 <div>
223 #if ($xwiki.isEditCommentFieldHidden())
224 <input type="hidden" name="comment" value="$!escapetool.xml($request.comment)" />
225 #else
226 <label for="commentinput">$services.localization.render('core.comment')</label>
227 <input type="text" name="comment" id="commentinput" value="$!escapetool.xml($request.comment)"
228 title="$services.localization.render('core.comment.tooltip')" />
229 #end
230 </div>
231 #end
232 <div class="buttons">
233 <span class="buttonwrapper">
234 <input type="submit" name="action_upload" class="button " value='$services.localization.render("${translationPrefix}.upload.submit")' title='$services.localization.render("${translationPrefix}.upload.submit")'/>
235 </span>
236 </div>
237 </form>
238 {{/html}}
239 #attachmentPicker_displayEndFrame ([])
240 #end
241
242 #**
243 * Displays the "empty value" box, used for unsetting the field value.
244 *
245 * @param $targetDocument the document being modified
246 * @param $targetAttachDocument the document that the attachments will the loaded from/saved to
247 * @param $options generic picker options
248 * @param $currentValue the currently selected file, used for determining if the empty box should be highlighted as the current value
249 *#
250 #macro (attachmentPicker_displayAttachmentGalleryEmptyValue $targetDocument, $targetAttachDocument, $options, $currentValue)
251 #if ("$!{options.get('defaultValue')}" != '')
252 #set ($reference = ${options.get('defaultValue')})
253 #set ($docNameLimit = $reference.indexOf('@'))
254 #if ($docNameLimit > 0)
255 #set ($docName = $reference.substring(0, $docNameLimit))
256 #else
257 #set ($docName = $targetAttachDocument.fullName)
258 #end
259 #set ($attachmentName = $reference.substring($mathtool.add($docNameLimit, 1)))
260 #set ($defaultAttachment = $xwiki.getDocument($docName).getAttachment($attachmentName))
261 #if ($defaultAttachment.isImage())
262 #set($dcssClass = 'gallery_image')
263 #end
264 #end
265 #attachmentPicker_displayStartFrame({'cssClass' : "gallery_emptyChoice $!{dcssClass}", 'text' : $services.localization.render("${translationPrefix}.default"), 'value' : "${options.defaultValue}"} $currentValue)
266 #attachmentPicker_displayAttachmentDetails($defaultAttachment $options)
267 #set ($returnURL = $escapetool.url($doc.getURL('view', $request.queryString)))
268 #set ($selectURL = $targetDocument.getURL(${options.get('docAction')}, "${options.get('classname')}_${options.get('object')}_${options.get('property')}=&form_token=$!{services.csrf.getToken()}"))
269 #attachmentPicker_displayEndFrame ([{'name' : 'select', 'url' : $selectURL}])
270 #end
271 {{/velocity}}
272
273 {{velocity}}
274 #if ($request.docname)
275 #set ($targetDocument = $xwiki.getDocument($request.docname))
276 #if ($request.targetdocname)
277 ## Use the target document if it exists.
278 #set ($targetAttachDocument = $xwiki.getDocument($request.targetdocname))
279 #else
280 ## Otherwise, just use the current document as the target to save/load attachments
281 #set ($targetAttachDocument = $targetDocument)
282 #end
283 #if ("$!{request.savemode}" == 'direct')
284 #set($docAction = 'save')
285 #else
286 #set($docAction = $targetAttachDocument.getDefaultEditMode())
287 #end
288 #set ($filter = [])
289 #set ($rawfilter = '')
290 #if ("$!{request.filter}" != '')
291 #foreach ($value in $request.filter.trim().split('\s*+[,|; ]\s*+'))
292 #if ("$!value" != '')
293 #set ($discard = $filter.add($value.toLowerCase()))
294 #set ($rawfilter = "${rawfilter}, ${value}")
295 #end
296 #end
297 #if ($rawfilter != '')
298 #set ($rawfilter = $rawfilter.substring(2))
299 #end
300 #end
301 #if ("$!{request.displayImage}" == 'true')
302 #set ($displayImage = true)
303 #else
304 #set ($displayImage = false)
305 #end
306 ### Determine attachment sorting
307 #set($sortAttachmentsBy = "$!{request.sortAttachmentsBy}")
308 #set ($validAttachmentProperties = ['filename', 'date', 'filesize', 'author', 'version', 'mimeType'])
309 #if($sortAttachmentsBy == '' || $validAttachmentProperties.indexOf($sortAttachmentsBy) == -1)
310 ### Default to sorting by filename, sort not requested.
311 #set($sortAttachmentsBy = "filename")
312 #end
313 ### Set attachment sorting direction
314 #if($sortAttachmentsBy == 'date')
315 ### Sort the date descending
316 #set($sortAttachmentsBy = "date:desc")
317 #else
318 ### Sort everything else ascending
319 #set($sortAttachmentsBy = "${sortAttachmentsBy}:asc")
320 #end
321 #set ($options = {
322 'classname' : ${request.get('classname')},
323 'object' : $!{numbertool.toNumber($request.object).intValue()},
324 'property' : ${request.property},
325 'displayImage' : ${displayImage},
326 'docAction' : ${docAction},
327 'defaultValue' : "$!{request.defaultValue}",
328 'rawfilter': "$!{rawfilter}",
329 'filter': ${filter},
330 'sortAttachmentsBy': ${sortAttachmentsBy},
331 'versionSummary': $request.versionSummary.equals('true')
332 })
333 $!targetDocument.use($targetDocument.getObject($options.classname, $options.object))##
334 #attachmentPicker_displayAttachmentGallery($targetDocument, $targetAttachDocument, $options)
335
336 #set ($cancelLinkName = $services.rendering.escape($services.rendering.escape($services.localization.render("${translationPrefix}.cancel"), 'xwiki/2.1'), 'xwiki/2.1'))
337 #set ($cancelLinkTarget = $services.rendering.escape($services.model.serialize($targetDocument), 'xwiki/2.1'))
338 (% class="gallery_buttons buttons" %)(((
339 (% class="buttonwrapper secondary" %)[[$cancelLinkName>>$cancelLinkTarget||class="button secondary" id="attachment-picker-close"]]
340 )))
341 #end
342 {{/velocity}}

Tips

You can click on the arrows next to the breadcrumb elements to quickly navigate to sibling and children pages.

Need help?

If you need help with XWiki you can contact: