From 9dbdf31f8c1569af0bead5bf47a58d74acd2fb64 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Tue, 15 May 2012 10:51:00 +0800 Subject: [PATCH] MDL-32867 Display a list of references pointing to the file in filemanager --- files/renderer.php | 13 ++++++++++--- lang/en/repository.php | 3 +++ lib/filebrowser/file_info.php | 14 ++++++++++++++ lib/form/filemanager.js | 32 ++++++++++++++++++++++++++++++-- lib/outputrequirementslib.php | 3 ++- repository/draftfiles_ajax.php | 28 ++++++++++++++++++++++++++++ theme/base/style/filemanager.css | 5 +++++ 7 files changed, 92 insertions(+), 6 deletions(-) diff --git a/files/renderer.php b/files/renderer.php index 5746a464998..64f5fa15ee0 100644 --- a/files/renderer.php +++ b/files/renderer.php @@ -322,13 +322,18 @@ class core_files_renderer extends plugin_renderer_base { * disabled if they are not applicable for the particular file; * * There may be present elements with classes 'fp-original', 'fp-datemodified', 'fp-datecreated', - * 'fp-size', 'fp-dimensions'. They will receive additional class 'fp-unknown' if information - * is unavailable. If there is information available, the content of embedded element - * with class 'fp-value' will be substituted with the value; + * 'fp-size', 'fp-dimensions', 'fp-reflist'. They will receive additional class 'fp-unknown' if + * information is unavailable. If there is information available, the content of embedded + * element with class 'fp-value' will be substituted with the value; * * The value of Original ('fp-original') is loaded in separate request. When it is applicable * but not yet loaded the 'fp-original' element receives additional class 'fp-loading'; * + * The value of 'Aliases/Shortcuts' ('fp-reflist') is also loaded in separate request. When it + * is applicable but not yet loaded the 'fp-original' element receives additional class + * 'fp-loading'. The string explaining that XX references exist will replace content of element + * 'fp-refcount'. Inside '.fp-reflist .fp-value' each reference will be enclosed in
  • ; + * * Elements with classes 'fp-file-update', 'fp-file-download', 'fp-file-delete', 'fp-file-zip', * 'fp-file-unzip', 'fp-file-setmain' and 'fp-file-cancel' will hold corresponding onclick * events (there may be several elements with class 'fp-file-cancel'); @@ -371,6 +376,8 @@ class core_files_renderer extends plugin_renderer_base { : '.$icon_progress.' '.$strloading.' + : +

    '.$icon_progress.' '.$strloading.'

      diff --git a/lang/en/repository.php b/lang/en/repository.php index 82a6b7b0bc1..42c8658591e 100644 --- a/lang/en/repository.php +++ b/lang/en/repository.php @@ -168,6 +168,8 @@ $string['popup'] = 'Click "Login" button to login'; $string['popupblockeddownload'] = 'The downloading window is blocked, please allow the popup window, and try again.'; $string['preview'] = 'Preview'; $string['readonlyinstance'] = 'You cannot edit/delete a read-only instance'; +$string['referencesexist'] = 'There are {$a} alias/shortcut files that use this file as their source'; +$string['referenceslist'] = 'Aliases/Shortcuts'; $string['refresh'] = 'Refresh'; $string['refreshnonjsfilepicker'] = 'Please close this window and refresh non-javascript file picker'; $string['removed'] = 'Repository removed'; @@ -199,6 +201,7 @@ $string['unknownoriginal'] = 'Unknown'; $string['upload'] = 'Upload this file'; $string['uploading'] = 'Uploading...'; $string['uploadsucc'] = 'The file has been uploaded successfully'; +$string['undisclosedreference'] = '(Undisclosed)'; $string['uselatestfile'] = 'Use latest file'; $string['usercontextrepositorydisabled'] = 'You cannot edit this repository in user context'; $string['usenonjsfilemanager'] = 'Open file manager in new window'; diff --git a/lib/filebrowser/file_info.php b/lib/filebrowser/file_info.php index 44069114762..e53640b3076 100644 --- a/lib/filebrowser/file_info.php +++ b/lib/filebrowser/file_info.php @@ -226,6 +226,20 @@ abstract class file_info { return 0; } + /** + * Returns the localised human-readable name of the file together with + * virtual path + * + * @return string + */ + public function get_readable_fullname() { + $fpath = array(); + for ($parent = $this; $parent; $parent = $parent->get_parent()) { + array_unshift($fpath, $parent->get_visible_name()); + } + return join('/', $fpath); + } + /** * Create new directory, may throw exception - make sure * params are valid. diff --git a/lib/form/filemanager.js b/lib/form/filemanager.js index 453fc76fb7f..efe355afb66 100644 --- a/lib/form/filemanager.js +++ b/lib/form/filemanager.js @@ -831,7 +831,7 @@ M.form_filemanager.init = function(Y, options) { }); selectnode.all('.fp-author input, .fp-license select').set('disabled',(node.type == 'folder')?'disabled':''); // display static information about a file (when known) - var attrs = ['datemodified','datecreated','size','dimensions','original']; + var attrs = ['datemodified','datecreated','size','dimensions','original','reflist']; for (var i in attrs) { if (selectnode.one('.fp-'+attrs[i])) { var value = (node[attrs[i]+'_f']) ? node[attrs[i]+'_f'] : (node[attrs[i]] ? node[attrs[i]] : ''); @@ -853,7 +853,7 @@ M.form_filemanager.init = function(Y, options) { scope: this, params: {'filepath':node.filepath,'filename':node.fullname}, callback: function(id, obj, args) { - // check if we did not select another file yet + // check if we did not select another file meanwhile var scope = args.scope; if (scope.selectui.fileinfo && node && scope.selectui.fileinfo.filepath == node.filepath && @@ -869,6 +869,34 @@ M.form_filemanager.init = function(Y, options) { } }, false); } + // load references list if applicable + selectnode.one('.fp-refcount').setContent(node.refcount ? M.util.get_string('referencesexist', 'repository', node.refcount) : ''); + if (node.refcount && !node.reflist) { + selectnode.one('.fp-reflist').removeClass('fp-unknown').addClass('fp-loading'); + this.request({ + action: 'getreferences', + scope: this, + params: {'filepath':node.filepath,'filename':node.fullname}, + callback: function(id, obj, args) { + // check if we did not select another file meanwhile + var scope = args.scope; + if (scope.selectui.fileinfo && node && + scope.selectui.fileinfo.filepath == node.filepath && + scope.selectui.fileinfo.fullname == node.fullname) { + selectnode.one('.fp-reflist').removeClass('fp-loading'); + if (obj.references) { + node.reflist = ''; + for (var i in obj.references) { + node.reflist += '
    • '+obj.references[i]+'
    • '; + } + selectnode.one('.fp-reflist .fp-value').setContent(node.reflist); + } else { + selectnode.one('.fp-reflist .fp-value').setContent(''); + } + } + } + }, false); + } // show panel this.selectui.show(); }, diff --git a/lib/outputrequirementslib.php b/lib/outputrequirementslib.php index 648a4ed29ef..bdf3b814f7c 100644 --- a/lib/outputrequirementslib.php +++ b/lib/outputrequirementslib.php @@ -445,7 +445,8 @@ class page_requirements_manager { array('nofilesattached', 'repository'), array('filepicker', 'repository'), array('logout', 'repository'), array('nofilesavailable', 'repository'), array('norepositoriesavailable', 'repository'), array('fileexistsdialogheader', 'repository'), array('fileexistsdialog_editor', 'repository'), - array('fileexistsdialog_filemanager', 'repository'), array('renameto', 'repository') + array('fileexistsdialog_filemanager', 'repository'), array('renameto', 'repository'), + array('referencesexist', 'repository') )); break; case 'core_comment': diff --git a/repository/draftfiles_ajax.php b/repository/draftfiles_ajax.php index 618055146a3..287f8514581 100644 --- a/repository/draftfiles_ajax.php +++ b/repository/draftfiles_ajax.php @@ -395,6 +395,34 @@ switch ($action) { } die; + case 'getreferences': + $filename = required_param('filename', PARAM_FILE); + $filepath = required_param('filepath', PARAM_PATH); + + $fs = get_file_storage(); + $file = $fs->get_file($user_context->id, 'user', 'draft', $draftid, $filepath, $filename); + if (!$file) { + echo json_encode(false); + } else { + $source = unserialize($file->get_source()); + $return = array('filename' => $filename, 'filepath' => $filepath, 'references' => array()); + $browser = get_file_browser(); + if (isset($source->original)) { + $reffiles = $fs->search_references($source->original); + foreach ($reffiles as $reffile) { + $refcontext = get_context_instance_by_id($reffile->get_contextid()); + $fileinfo = $browser->get_file_info($refcontext, $reffile->get_component(), $reffile->get_filearea(), $reffile->get_itemid(), $reffile->get_filepath(), $reffile->get_filename()); + if (empty($fileinfo)) { + $return['references'][] = get_string('undisclosedreference', 'repository'); + } else { + $return['references'][] = $fileinfo->get_readable_fullname(); + } + } + } + echo json_encode((object)$return); + } + die; + default: // no/unknown action? echo json_encode(false); diff --git a/theme/base/style/filemanager.css b/theme/base/style/filemanager.css index 1d1c1eac5eb..bcc19f431ac 100644 --- a/theme/base/style/filemanager.css +++ b/theme/base/style/filemanager.css @@ -291,6 +291,11 @@ a.ygtvspacer:hover {color: transparent;text-decoration: none;} .filemanager.fp-select .fp-original .fp-originloading {display:none;} .filemanager.fp-select .fp-original.fp-loading .fp-originloading {display:inline;} +.filemanager.fp-select .fp-reflist.fp-unknown {display:none;} +.filemanager.fp-select .fp-reflist .fp-reflistloading {display:none;} +.filemanager.fp-select .fp-reflist.fp-loading .fp-reflistloading {display:inline;} +.filemanager.fp-select .fp-reflist .fp-value {max-width:400px;max-height:50px;overflow:auto;} + /* * Create folder dialogue (File Manager only) */