From 22c7bbfcd42a8785da4d443d5573981b2ee1d220 Mon Sep 17 00:00:00 2001 From: Julian Seidenberg Date: Fri, 8 Mar 2013 16:02:38 +1300 Subject: [PATCH] NEW UploadField displays a warning before overwriting files (only relevant if config.yml: Upload:replaceFile = true). --- _config/uploadfield.yml | 3 +- css/AssetUploadField.css | 6 ++-- docs/en/reference/uploadfield.md | 4 +-- filesystem/Upload.php | 40 +++++++++++++----------- forms/UploadField.php | 17 +++++++++- javascript/UploadField.js | 33 +++++++++++++++++++ javascript/UploadField_uploadtemplate.js | 2 ++ javascript/lang/de_DE.js | 3 +- javascript/lang/en_US.js | 3 +- scss/_elementMixins.scss | 2 +- 10 files changed, 85 insertions(+), 28 deletions(-) diff --git a/_config/uploadfield.yml b/_config/uploadfield.yml index ccd35fbf8..eab120d40 100644 --- a/_config/uploadfield.yml +++ b/_config/uploadfield.yml @@ -13,4 +13,5 @@ UploadField: downloadTemplateName: 'ss-uploadfield-downloadtemplate' fileEditFields: fileEditActions: - fileEditValidator: \ No newline at end of file + fileEditValidator: + overwriteWarning: true # Warning before overwriting existing file (only relevant when Upload: replaceFile is true) \ No newline at end of file diff --git a/css/AssetUploadField.css b/css/AssetUploadField.css index 9a8816208..a6380044f 100644 --- a/css/AssetUploadField.css +++ b/css/AssetUploadField.css @@ -52,9 +52,9 @@ body.cms.ss-uploadfield-edit-iframe .fieldholder-small label, .composite.ss-asse .ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-actions { position: absolute; top: 0; right: 0; left: 0; z-index: 0; color: #f00; font-size: 14px; } .ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-actions .ss-ui-button { background: none; border: 0; -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; text-shadow: none; color: white; float: right; } .ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-actions .ss-ui-button.ss-uploadfield-item-delete { display: none; } -.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-actions .ss-ui-button.ss-uploadfield-item-cancel { -webkit-border-radius: 0; -moz-border-radius: 0; -ms-border-radius: 0; -o-border-radius: 0; border-radius: 0; border-left: 1px solid rgba(255, 255, 255, 0.2); margin-top: 0px; cursor: pointer; opacity: 0.9; } -.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-actions .ss-ui-button.ss-uploadfield-item-cancel:hover { opacity: 1; } -.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-actions .ss-ui-button.ss-uploadfield-item-cancel .ui-icon { display: block; margin: 0; position: realtive; top: 8px; } +.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-actions .ss-ui-button.ss-uploadfield-item-cancel, .ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-actions .ss-ui-button.ss-uploadfield-item-overwrite-warning { -webkit-border-radius: 0; -moz-border-radius: 0; -ms-border-radius: 0; -o-border-radius: 0; border-radius: 0; border-left: 1px solid rgba(255, 255, 255, 0.2); margin-top: 0px; cursor: pointer; opacity: 0.9; } +.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-actions .ss-ui-button.ss-uploadfield-item-cancel:hover, .ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-actions .ss-ui-button.ss-uploadfield-item-overwrite-warning:hover { opacity: 1; } +.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-actions .ss-ui-button.ss-uploadfield-item-cancel .ui-icon, .ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-actions .ss-ui-button.ss-uploadfield-item-overwrite-warning .ui-icon { display: block; margin: 0; position: realtive; top: 8px; } .ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-actions .ss-ui-button.ss-uploadfield-item-edit { opacity: 0.9; padding-top: 1px; padding-bottom: 0; height: 100%; -webkit-border-radius: 0; -moz-border-radius: 0; -ms-border-radius: 0; -o-border-radius: 0; border-radius: 0; } .ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-actions .ss-ui-button.ss-uploadfield-item-edit.ui-state-hover { background: none; opacity: 1; } .ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-actions .ss-ui-button.ss-uploadfield-item-edit.ui-state-hover span.toggle-details { opacity: 1; } diff --git a/docs/en/reference/uploadfield.md b/docs/en/reference/uploadfield.md index 15867f5ab..4e07b9b77 100644 --- a/docs/en/reference/uploadfield.md +++ b/docs/en/reference/uploadfield.md @@ -225,9 +225,9 @@ You can also configure the underlying `[api:Upload]` class, by using the YAML co :::yaml Upload: - # Globally disables automatic renaming of files + # Globally disables automatic renaming of files and displays a warning before overwriting an existing file replaceFile: true - + ## TODO: Using the UploadField in a frontend form *At this moment the UploadField not yet fully supports being used on a frontend diff --git a/filesystem/Upload.php b/filesystem/Upload.php index 7c0548cef..909c57beb 100644 --- a/filesystem/Upload.php +++ b/filesystem/Upload.php @@ -153,24 +153,27 @@ class Upload extends Controller { // if filename already exists, version the filename (e.g. test.gif to test1.gif) if(!$this->replaceFile) { - while(file_exists("$base/$relativeFilePath")) { - $i = isset($i) ? ($i+1) : 2; - $oldFilePath = $relativeFilePath; - // make sure archives retain valid extensions - if(substr($relativeFilePath, strlen($relativeFilePath) - strlen('.tar.gz')) == '.tar.gz' || - substr($relativeFilePath, strlen($relativeFilePath) - strlen('.tar.bz2')) == '.tar.bz2') { - $relativeFilePath = preg_replace('/[0-9]*(\.tar\.[^.]+$)/', $i . '\\1', $relativeFilePath); - } else if (strpos($relativeFilePath, '.') !== false) { - $relativeFilePath = preg_replace('/[0-9]*(\.[^.]+$)/', $i . '\\1', $relativeFilePath); - } else if (strpos($relativeFilePath, '_') !== false) { - $relativeFilePath = preg_replace('/_([^_]+$)/', '_'.$i, $relativeFilePath); - } else { - $relativeFilePath .= '_'.$i; - } - if($oldFilePath == $relativeFilePath && $i > 2) { - user_error("Couldn't fix $relativeFilePath with $i tries", E_USER_ERROR); - } - } + while(file_exists("$base/$relativeFilePath")) { + $i = isset($i) ? ($i+1) : 2; + $oldFilePath = $relativeFilePath; + // make sure archives retain valid extensions + if(substr($relativeFilePath, strlen($relativeFilePath) - strlen('.tar.gz')) == '.tar.gz' || + substr($relativeFilePath, strlen($relativeFilePath) - strlen('.tar.bz2')) == '.tar.bz2') { + $relativeFilePath = preg_replace('/[0-9]*(\.tar\.[^.]+$)/', $i . '\\1', $relativeFilePath); + } else if (strpos($relativeFilePath, '.') !== false) { + $relativeFilePath = preg_replace('/[0-9]*(\.[^.]+$)/', $i . '\\1', $relativeFilePath); + } else if (strpos($relativeFilePath, '_') !== false) { + $relativeFilePath = preg_replace('/_([^_]+$)/', '_'.$i, $relativeFilePath); + } else { + $relativeFilePath .= '_'.$i; + } + if($oldFilePath == $relativeFilePath && $i > 2) { + user_error("Couldn't fix $relativeFilePath with $i tries", E_USER_ERROR); + } + } + } else { + //reset the ownerID to the current member when replacing files + $this->file->OwnerID = (Member::currentUser() ? Member::currentUser()->ID : 0); } if(file_exists($tmpFile['tmp_name']) && copy($tmpFile['tmp_name'], "$base/$relativeFilePath")) { @@ -178,6 +181,7 @@ class Upload extends Controller { // This is to prevent it from trying to rename the file $this->file->Name = basename($relativeFilePath); $this->file->write(); + $this->extend('onAfterLoad', $this->file); //to allow extensions to e.g. create a version after an upload return true; } else { $this->errors[] = _t('File.NOFILESIZE', 'Filesize is zero bytes.'); diff --git a/forms/UploadField.php b/forms/UploadField.php index e117f357e..3d7b113e4 100644 --- a/forms/UploadField.php +++ b/forms/UploadField.php @@ -141,7 +141,11 @@ class UploadField extends FileField { * @example 'getCMSValidator' * @var string */ - 'fileEditValidator' => null + 'fileEditValidator' => null, + /** + * Show a warning when overwriting a file + */ + 'overwriteWarning' => true, ); /** @@ -416,6 +420,17 @@ class UploadField extends FileField { if (is_numeric($config['maxNumberOfFiles']) && $this->getItems()->count()) { $configOverwrite['maxNumberOfFiles'] = $config['maxNumberOfFiles'] - $this->getItems()->count(); } + + //get all the existing files in the current folder + if ($this->getConfig('overwriteWarning')) { + $folder = Folder::find_or_make($this->getFolderName()); + $files = glob( $folder->getFullPath() . '/*' ); + $config['existingFiles'] = array_map("basename", $files);; + + //add overwrite warning error message to the config object sent to Javascript + $config['errorMessages']['overwriteWarning'] = + _t('UploadField.OVERWRITEWARNING','File with the same name already exists'); + } $config = array_merge($config, $this->ufConfig, $configOverwrite); diff --git a/javascript/UploadField.js b/javascript/UploadField.js index f5f02edd0..6e908d159 100644 --- a/javascript/UploadField.js +++ b/javascript/UploadField.js @@ -48,6 +48,39 @@ return result; }, + _onSend: function (e, data) { + //check the array of existing files to see if we are trying to upload a file that already exists + var that = this; + var config = $('div.ss-upload').entwine('ss').getConfig(); + var existingFiles = []; + if (typeof (config.existingFiles) !== "undefined") { + existingFiles = config.existingFiles; + } + + var fileExists = false; + jQuery.each(existingFiles,function(){ + if ($(this)[0].toLowerCase() === data.files[0].name.toLowerCase()) { + fileExists = true; + return; + } + }); + + if (fileExists) { + //display the dialogs with the question to overwrite or not + data.context.find('.ss-uploadfield-item-status').text(config.errorMessages.overwriteWarning).css('max-width','75%'); + data.context.find('.ss-uploadfield-item-progress').hide(); + data.context.find('.ss-uploadfield-item-overwrite').show(); + data.context.find('.ss-uploadfield-item-overwrite-warning').on('click', function(){ + data.context.find('.ss-uploadfield-item-progress').show(); + data.context.find('.ss-uploadfield-item-overwrite').hide(); + + //upload only if the "overwrite" button is clicked + $.blueimpUI.fileupload.prototype._onSend.call(that, e, data); + }); + } else { //regular file upload + return $.blueimpUI.fileupload.prototype._onSend.call(that, e, data); + } + }, _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) { $.blueimpUI.fileupload.prototype._onAlways.call(this, jqXHRorResult, textStatus, jqXHRorError, options); if (this._active === 0) { diff --git a/javascript/UploadField_uploadtemplate.js b/javascript/UploadField_uploadtemplate.js index a41c57570..821850416 100644 --- a/javascript/UploadField_uploadtemplate.js +++ b/javascript/UploadField_uploadtemplate.js @@ -21,6 +21,8 @@ window.tmpl.cache['ss-uploadfield-uploadtemplate'] = tmpl( '{% } %}' + '{% } %}' + '
' + + '
'+ + '
' + '' + '' + diff --git a/javascript/lang/de_DE.js b/javascript/lang/de_DE.js index 57f636e21..dffd52532 100644 --- a/javascript/lang/de_DE.js +++ b/javascript/lang/de_DE.js @@ -34,6 +34,7 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { 'UploadField.EMPTYRESULT': 'Leere Datei erhalten', 'UploadField.LOADING': 'Lädt ...', 'UploadField.Editing': 'Bearbeite ...', - 'UploadField.Uploaded': 'Hochgeladen' + 'UploadField.Uploaded': 'Hochgeladen', + 'UploadField.OVERWRITEWARNING': 'Datei mit diesem Namen existiert bereits' }); } \ No newline at end of file diff --git a/javascript/lang/en_US.js b/javascript/lang/en_US.js index 5432118e0..076f18db6 100644 --- a/javascript/lang/en_US.js +++ b/javascript/lang/en_US.js @@ -35,6 +35,7 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { 'UploadField.EMPTYRESULT': 'Empty file upload result', 'UploadField.LOADING': 'Loading ...', 'UploadField.Editing': 'Editing ...', - 'UploadField.Uploaded': 'Uploaded' + 'UploadField.Uploaded': 'Uploaded', + 'UploadField.OVERWRITEWARNING': 'File with the same name already exists' }); } diff --git a/scss/_elementMixins.scss b/scss/_elementMixins.scss index 152b7dbf0..e973541e6 100644 --- a/scss/_elementMixins.scss +++ b/scss/_elementMixins.scss @@ -29,7 +29,7 @@ // TODO tmp hack until we have permissions and can disable delete display: none; } - &.ss-uploadfield-item-cancel{ + &.ss-uploadfield-item-cancel, &.ss-uploadfield-item-overwrite-warning { @include border-radius(0); border-left:1px solid rgba(#fff, 0.2); margin-top:0px;