# Wiki source code of Attachments

Last modified by Alexandru Colesnicov on 2019/07/24 16:42
Export
Office Formats
Export as PDF
Other Formats
Export as HTML

Show last authors

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

# Applications

# Tips

Did you know that you can improve XWiki? Take 5 minutes to fill this survey and help this open source project!

# Need help?

If you need help with XWiki you can contact:

- Community Support
- Professional Support

XWiki Debian 11.5