Wiki source code of Attachments
Last modified by superadmin on 2017/11/28 14:52
| 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&docAction=$!{escapetool.url($options.get('docAction'))}&targetdocname=$!{escapetool.url($targetAttachDocument.fullName)}&docname=$!{escapetool.url($targetDocument.fullName)}&fieldname=$!{escapetool.url($options.get('classname'))}_$!{escapetool.url($options.get('object'))}_$!{escapetool.url($options.get('property'))}&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}} |