MDL-80447 repository_googledocs: Switch to use core/pubsub
This commit is contained in:
@@ -117,7 +117,6 @@ $string['errordoublereference'] = 'Unable to overwrite file with a link because
|
||||
$string['errornotyourfile'] = 'You can only pick files which you added.';
|
||||
$string['erroruniquename'] = 'Repository instance name should be unique';
|
||||
$string['errorpostmaxsize'] = 'The file you tried to upload is too large for the server to process.';
|
||||
$string['erroruploadfailed'] = 'File upload failed. Please check your files and try again.';
|
||||
$string['errorwhilecommunicatingwith'] = 'Error while communicating with the repository \'{$a}\'.';
|
||||
$string['errorwhiledownload'] = 'An error occurred while downloading the file: {$a}';
|
||||
$string['existingrepository'] = 'This repository already exists';
|
||||
@@ -246,7 +245,6 @@ $string['typenotvisible'] = 'Type not visible';
|
||||
$string['unknownoriginal'] = 'Unknown';
|
||||
$string['upload'] = 'Upload this file';
|
||||
$string['uploaderror'] = 'File upload error';
|
||||
$string['uploadfilesdrop'] = 'Drag and drop a file to upload, or click to select';
|
||||
$string['uploading'] = 'Uploading...';
|
||||
$string['uploadsucc'] = 'The file has been uploaded successfully';
|
||||
$string['unknownsource'] = 'Unknown source';
|
||||
|
||||
+19
-210
@@ -1633,7 +1633,7 @@ M.core_filepicker.init = function(Y, options) {
|
||||
this.active_repo.help = data.help?data.help:null;
|
||||
this.active_repo.manage = data.manage?data.manage:null;
|
||||
this.active_repo.uploadfile = data.uploadfile ? data.uploadfile : null;
|
||||
this.active_repo.uploadurl = data.uploadurl ? data.uploadurl : null;
|
||||
this.active_repo.uploadevent = data.uploadevent ? data.uploadevent : null;
|
||||
// Warning message related to the file reference option, if applicable to the given repository.
|
||||
this.active_repo.filereferencewarning = data.filereferencewarning ? data.filereferencewarning : null;
|
||||
this.print_header();
|
||||
@@ -2005,217 +2005,26 @@ M.core_filepicker.init = function(Y, options) {
|
||||
managelnk.simulate('click')
|
||||
});
|
||||
|
||||
// New Upload functionality.
|
||||
toolbar.one('.fp-tb-uploadfile').one('a,button').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
var repoId = this.active_repo.id;
|
||||
var contextId = this.options.context.id;
|
||||
var draftidRef = {value: null}; // Store draftid between uploads.
|
||||
var uploadurl = this.active_repo.uploadurl;
|
||||
|
||||
require([
|
||||
'core/modal_factory',
|
||||
'core/modal_events',
|
||||
'core/dropzone',
|
||||
'core/notification',
|
||||
'core/str',
|
||||
'core/templates'
|
||||
],
|
||||
function(ModalFactory, ModalEvents, DropZone, Notification, Str, Templates) {
|
||||
// Create a Modal box with a dropzone where files can be uploaded.
|
||||
function openUploadModal() {
|
||||
Templates.render('core/dropzone', {}).then(function(bodyHtml) {
|
||||
ModalFactory.create({
|
||||
type: ModalFactory.types.SAVE_CANCEL,
|
||||
title: Str.get_string('upload'),
|
||||
body: bodyHtml,
|
||||
large: true
|
||||
}).then(function(modal) {
|
||||
modal.getRoot().on(ModalEvents.shown, function() {
|
||||
initDropzone(modal);
|
||||
});
|
||||
modal.getRoot().on(ModalEvents.hidden, function() {
|
||||
modal.destroy();
|
||||
});
|
||||
modal.getRoot().on(ModalEvents.save, function(ev) {
|
||||
commitFiles(ev, modal, toolbar);
|
||||
});
|
||||
modal.getRoot().on(ModalEvents.cancel, function() {
|
||||
modal.hide();
|
||||
});
|
||||
modal.show();
|
||||
});
|
||||
});
|
||||
}
|
||||
openUploadModal();
|
||||
|
||||
// Create dropzone inside the modal.
|
||||
function initDropzone(modal) {
|
||||
const $body = modal.getBody();
|
||||
|
||||
const dropzoneContainer = $body.find('.dropzone-container').get(0);
|
||||
const dz = new DropZone(dropzoneContainer, '*', function(files) {
|
||||
handleDroppedFiles(files, modal);
|
||||
});
|
||||
|
||||
// Asynchronously load and set the label.
|
||||
Str.get_string('dropfiles', 'repository').then(function(label) {
|
||||
dz.setLabel(label);
|
||||
});
|
||||
|
||||
dz.init();
|
||||
}
|
||||
|
||||
// Handle file upload to save it as draft.
|
||||
function handleDroppedFiles(files, modal) {
|
||||
var currentIndex = 0;
|
||||
|
||||
function uploadNextFile() {
|
||||
if (currentIndex >= files.length) {
|
||||
return;
|
||||
// Repository upload.
|
||||
// If repository supports upload, it needs to provide 'uploadevent' in its response to 'list' command.
|
||||
// This event will be used to trigger the upload process.
|
||||
// Repository will need to subscribe to this event and launch its own upload process.
|
||||
toolbar.one('.fp-tb-uploadfile').one('a,button').on('click', (e) => {
|
||||
if (this.active_repo.uploadevent) {
|
||||
e.preventDefault();
|
||||
require(['core/pubsub'], (PubSub) => {
|
||||
PubSub.publish(this.active_repo.uploadevent, {
|
||||
repoId: this.active_repo.id,
|
||||
contextId: this.options.context.id,
|
||||
callback: () => {
|
||||
// Refresh the file list after upload is done.
|
||||
if (!this.active_repo.norefresh) {
|
||||
this.list({path: this.currentpath});
|
||||
}
|
||||
}
|
||||
|
||||
var file = files[currentIndex];
|
||||
currentIndex++;
|
||||
|
||||
var formData = new FormData();
|
||||
formData.append('repo_upload_file', file);
|
||||
formData.append('repo_id', repoId);
|
||||
formData.append('contextid', contextId);
|
||||
formData.append('sesskey', M.cfg.sesskey);
|
||||
formData.append('action', 'upload');
|
||||
|
||||
if (draftidRef.value) {
|
||||
formData.append('itemid', draftidRef.value);
|
||||
}
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', M.cfg.wwwroot + uploadurl, true);
|
||||
|
||||
xhr.onload = function() {
|
||||
var response = JSON.parse(this.responseText);
|
||||
if (response.error) {
|
||||
Notification.alert(
|
||||
Str.get_string('uploaderror', 'repository'),
|
||||
response.error,
|
||||
Str.get_string('close', 'repository')
|
||||
);
|
||||
} else {
|
||||
if (response.draftid && !draftidRef.value) {
|
||||
draftidRef.value = response.draftid;
|
||||
}
|
||||
renderUploadedFile(modal, response);
|
||||
|
||||
// Upload next file after this one finishes.
|
||||
uploadNextFile();
|
||||
}
|
||||
};
|
||||
|
||||
xhr.send(formData);
|
||||
}
|
||||
|
||||
// Start uploading files.
|
||||
uploadNextFile();
|
||||
}
|
||||
|
||||
// Render the uploaded file in a given modal.
|
||||
function renderUploadedFile(modal, response) {
|
||||
const $body = modal.getBody();
|
||||
let uploadFilesClass = 'uploaded-files';
|
||||
let $fileList = $body.find(`.${uploadFilesClass} ul`);
|
||||
|
||||
if ($fileList.length === 0) {
|
||||
// Load the string asynchronously.
|
||||
Str.get_string('attachedfiles', 'repository').then(function(label) {
|
||||
const uploadedFiles = document.createElement('div');
|
||||
uploadedFiles.className = uploadFilesClass + ' pt-4';
|
||||
const headingElement = document.createElement('h5');
|
||||
headingElement.textContent = label;
|
||||
uploadedFiles.appendChild(headingElement);
|
||||
uploadedFiles.appendChild(document.createElement('ul'));
|
||||
$body.append(uploadedFiles);
|
||||
|
||||
$fileList = $body.find(`.${uploadFilesClass} ul`);
|
||||
$fileList.append(`<li>${response.file}</li>`);
|
||||
});
|
||||
}
|
||||
|
||||
$fileList.append(`<li>${response.file}</li>`);
|
||||
}
|
||||
|
||||
// Commit uploaded draft files when user clicks save.
|
||||
function commitFiles(ev, modal, toolbar) {
|
||||
ev.preventDefault();
|
||||
|
||||
if (!draftidRef.value) {
|
||||
Notification.alert(
|
||||
Str.get_string('uploaderror', 'repository'),
|
||||
Str.get_string('nofilesattached', 'repository'),
|
||||
Str.get_string('close', 'repository')
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Show loading spinner using Moodle's core/loading template.
|
||||
Templates.render('core/loading', {size: 'lg'}).then(function(html) {
|
||||
// Create a full-page overlay with Moodle classes.
|
||||
const loadingOverlay = document.createElement('div');
|
||||
loadingOverlay.className = 'loading-overlay';
|
||||
loadingOverlay.className = 'fixed-top w-100 h-100 d-flex justify-content-center align-items-center';
|
||||
loadingOverlay.style.zIndex = '9999';
|
||||
loadingOverlay.style.backgroundColor = 'rgba(255, 255, 255, 0.8)';
|
||||
|
||||
// Create container for the loading spinner.
|
||||
const loadingContainer = document.createElement('div');
|
||||
loadingContainer.className = 'd-flex flex-column align-items-center';
|
||||
loadingContainer.innerHTML = html;
|
||||
|
||||
// Add text below the spinner.
|
||||
Str.get_string('uploading', 'repository').then(function(loadingText) {
|
||||
const loadingTextElement = document.createElement('p');
|
||||
loadingTextElement.className = 'mt-2';
|
||||
loadingTextElement.textContent = loadingText;
|
||||
loadingContainer.appendChild(loadingTextElement);
|
||||
});
|
||||
|
||||
loadingOverlay.appendChild(loadingContainer);
|
||||
document.body.appendChild(loadingOverlay);
|
||||
|
||||
var formData = new FormData();
|
||||
formData.append('action', 'commit');
|
||||
formData.append('repo_id', repoId);
|
||||
formData.append('contextid', contextId);
|
||||
formData.append('sesskey', M.cfg.sesskey);
|
||||
formData.append('itemid', draftidRef.value);
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', M.cfg.wwwroot + uploadurl, true);
|
||||
|
||||
xhr.onload = function() {
|
||||
// Remove loading overlay.
|
||||
if (loadingOverlay && loadingOverlay.parentNode) {
|
||||
loadingOverlay.parentNode.removeChild(loadingOverlay);
|
||||
}
|
||||
|
||||
let response = JSON.parse(xhr.responseText);
|
||||
if (response.error) {
|
||||
Notification.alert(
|
||||
Str.get_string('uploaderror', 'repository'),
|
||||
response.error,
|
||||
Str.get_string('close', 'repository')
|
||||
);
|
||||
} else {
|
||||
modal.hide();
|
||||
var refreshButton = toolbar.one('.fp-tb-refresh').one('a,button');
|
||||
if (refreshButton) {
|
||||
refreshButton.simulate('click');
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send(formData);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}, this);
|
||||
|
||||
// same with .fp-tb-help
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
define("repository_googledocs/upload",["exports","core/pubsub","core/modal_save_cancel","core/str","core/templates","core/modal_events","core/dropzone","core/config","core/notification"],(function(_exports,_pubsub,_modal_save_cancel,_str,_templates,_modal_events,_dropzone,config,_notification){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
|
||||
/**
|
||||
* Upload module for Google Docs repository.
|
||||
*
|
||||
* @module repository_googledocs/upload
|
||||
* @copyright 2025 Huong Nguyen <huongnv13@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_modal_save_cancel=_interopRequireDefault(_modal_save_cancel),_templates=_interopRequireDefault(_templates),_modal_events=_interopRequireDefault(_modal_events),_dropzone=_interopRequireDefault(_dropzone),config=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(config),_notification=_interopRequireDefault(_notification);let listenersRegistered=!1,droppedFiles=[];const initDropzone=modal=>{const $body=modal.getBody(),dropzoneContainer=$body.find(".repository_googledocs_dropzone_container").get(0),fileListContainer=$body.find("ul.repository_googledocs_files_list").get(0),dz=new _dropzone.default(dropzoneContainer,"*",(files=>{droppedFiles.push(...files);let fileListHTML="";for(let i=0;i<droppedFiles.length;i++)fileListHTML+="<li>"+droppedFiles[i].name+"</li>";fileListContainer.innerHTML=fileListHTML}));(0,_str.getString)("dropfiles","repository").then((label=>{dz.setLabel(label)})),dz.init()},commitFiles=(repoId,contextId,callback,files,modal)=>{const saveButton=modal.getFooter().find('[data-action="save"]'),formData=new FormData;formData.append("action","upload"),formData.append("repo_id",repoId),formData.append("contextid",contextId),formData.append("sesskey",config.sesskey);for(let i=0;i<files.length;i++)formData.append("files[]",files[i]);const xhr=new XMLHttpRequest;xhr.open("POST",config.wwwroot+"/repository/googledocs/repository_ajax.php",!1),xhr.onload=function(){const response=JSON.parse(xhr.responseText);response.error?(saveButton.removeAttr("disabled"),_notification.default.alert((0,_str.getString)("uploaderror","repository"),response.error,(0,_str.getString)("close","repository"))):(saveButton.removeAttr("disabled"),modal.hide(),callback())},xhr.send(formData)},registerEventListeners=()=>{listenersRegistered||((0,_pubsub.subscribe)("repository_googledocs_upload",(data=>{(data=>{_templates.default.render("repository_googledocs/upload_dialogue",{}).then((function(bodyHtml){return _modal_save_cancel.default.create({title:(0,_str.getString)("upload"),body:bodyHtml,large:!0}).then((function(modal){return modal.getRoot().on(_modal_events.default.shown,(()=>{droppedFiles=[],initDropzone(modal)})),modal.getRoot().on(_modal_events.default.hidden,(()=>{modal.destroy()})),modal.getRoot().on(_modal_events.default.save,(e=>{e.preventDefault(),commitFiles(data.repoId,data.contextId,data.callback,droppedFiles,modal)})),modal.getRoot().on(_modal_events.default.cancel,(()=>{modal.hide()})),modal.show(),modal}))}))})(data)})),listenersRegistered=!0)};_exports.init=()=>{registerEventListeners()}}));
|
||||
|
||||
//# sourceMappingURL=upload.min.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,150 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Upload module for Google Docs repository.
|
||||
*
|
||||
* @module repository_googledocs/upload
|
||||
* @copyright 2025 Huong Nguyen <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
import {subscribe} from 'core/pubsub';
|
||||
import SaveCancelModal from 'core/modal_save_cancel';
|
||||
import {getString} from 'core/str';
|
||||
import Templates from 'core/templates';
|
||||
import ModalEvents from 'core/modal_events';
|
||||
import Dropzone from 'core/dropzone';
|
||||
import * as config from 'core/config';
|
||||
import Notification from 'core/notification';
|
||||
|
||||
let listenersRegistered = false;
|
||||
let droppedFiles = [];
|
||||
|
||||
/**
|
||||
* Open the upload modal.
|
||||
*
|
||||
* @param {object} data Data passed from the event
|
||||
*/
|
||||
const openUploadModal = (data) => {
|
||||
Templates.render('repository_googledocs/upload_dialogue', {}).then(function(bodyHtml) {
|
||||
return SaveCancelModal.create({
|
||||
title: getString('upload'),
|
||||
body: bodyHtml,
|
||||
large: true,
|
||||
}).then(function(modal) {
|
||||
modal.getRoot().on(ModalEvents.shown, () => {
|
||||
droppedFiles = [];
|
||||
initDropzone(modal);
|
||||
});
|
||||
modal.getRoot().on(ModalEvents.hidden, () => {
|
||||
modal.destroy();
|
||||
});
|
||||
modal.getRoot().on(ModalEvents.save, (e) => {
|
||||
e.preventDefault();
|
||||
commitFiles(data.repoId, data.contextId, data.callback, droppedFiles, modal);
|
||||
});
|
||||
modal.getRoot().on(ModalEvents.cancel, () => {
|
||||
modal.hide();
|
||||
});
|
||||
modal.show();
|
||||
|
||||
return modal;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the dropzone inside the modal.
|
||||
*
|
||||
* @param {Modal} modal Modal instance
|
||||
*/
|
||||
const initDropzone = (modal) => {
|
||||
const $body = modal.getBody();
|
||||
const dropzoneContainer = $body.find('.repository_googledocs_dropzone_container').get(0);
|
||||
const fileListContainer = $body.find('ul.repository_googledocs_files_list').get(0);
|
||||
const dz = new Dropzone(dropzoneContainer, '*', (files) => {
|
||||
droppedFiles.push(...files);
|
||||
let fileListHTML = '';
|
||||
for (let i = 0; i < droppedFiles.length; i++) {
|
||||
fileListHTML += '<li>' + droppedFiles[i].name + '</li>';
|
||||
}
|
||||
fileListContainer.innerHTML = fileListHTML;
|
||||
});
|
||||
|
||||
getString('dropfiles', 'repository').then((label) => {
|
||||
dz.setLabel(label);
|
||||
});
|
||||
|
||||
dz.init();
|
||||
};
|
||||
|
||||
/**
|
||||
* Upload files to server.
|
||||
*
|
||||
* @param {Integer} repoId Repository ID
|
||||
* @param {Integer} contextId Context ID
|
||||
* @param {function} callback Callback function
|
||||
* @param {array} files Files to be uploaded
|
||||
* @param {Modal} modal Modal instance
|
||||
*/
|
||||
const commitFiles = (repoId, contextId, callback, files, modal) => {
|
||||
const saveButton = modal.getFooter().find('[data-action="save"]');
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'upload');
|
||||
formData.append('repo_id', repoId);
|
||||
formData.append('contextid', contextId);
|
||||
formData.append('sesskey', config.sesskey);
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
formData.append("files[]", files[i]);
|
||||
}
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', config.wwwroot + '/repository/googledocs/repository_ajax.php', false);
|
||||
xhr.onload = function() {
|
||||
const response = JSON.parse(xhr.responseText);
|
||||
if (response.error) {
|
||||
saveButton.removeAttr('disabled');
|
||||
Notification.alert(
|
||||
getString('uploaderror', 'repository'),
|
||||
response.error,
|
||||
getString('close', 'repository'),
|
||||
);
|
||||
} else {
|
||||
saveButton.removeAttr('disabled');
|
||||
modal.hide();
|
||||
callback();
|
||||
}
|
||||
};
|
||||
xhr.send(formData);
|
||||
};
|
||||
|
||||
/**
|
||||
* Register events.
|
||||
*/
|
||||
const registerEventListeners = () => {
|
||||
if (!listenersRegistered) {
|
||||
subscribe('repository_googledocs_upload', (data) => {
|
||||
openUploadModal(data);
|
||||
});
|
||||
listenersRegistered = true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the upload module.
|
||||
*/
|
||||
export const init = () => {
|
||||
registerEventListeners();
|
||||
};
|
||||
@@ -76,6 +76,7 @@ class repository_googledocs extends repository {
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array(), $readonly = 0) {
|
||||
global $PAGE;
|
||||
parent::__construct($repositoryid, $context, $options, $readonly = 0);
|
||||
|
||||
try {
|
||||
@@ -87,6 +88,8 @@ class repository_googledocs extends repository {
|
||||
if ($this->issuer && !$this->issuer->get('enabled')) {
|
||||
$this->disabled = true;
|
||||
}
|
||||
|
||||
$PAGE->requires->js_call_amd('repository_googledocs/upload', 'init');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -310,7 +313,7 @@ class repository_googledocs extends repository {
|
||||
'path' => $contentobj->get_navigation(),
|
||||
'list' => $contentobj->get_content_nodes($query, [$this, 'filter']),
|
||||
'uploadfile' => true,
|
||||
'uploadurl' => '/repository/googledocs/repository_ajax.php',
|
||||
'uploadevent' => 'repository_googledocs_upload',
|
||||
'repo_id' => $this->id,
|
||||
'contextid' => $this->context->id,
|
||||
'sesskey' => sesskey(),
|
||||
@@ -805,7 +808,7 @@ class repository_googledocs extends repository {
|
||||
* @return stdClass
|
||||
*/
|
||||
protected function get_file_summary(\repository_googledocs\rest $client, $fileid) {
|
||||
$fields = "id,name,owners,parents,mimeType,webContentLink,webViewLink,size,thumbnailLink,iconLink";
|
||||
$fields = "id,name,owners,parents";
|
||||
$params = [
|
||||
'fileid' => $fileid,
|
||||
'fields' => $fields
|
||||
@@ -1041,26 +1044,11 @@ class repository_googledocs extends repository {
|
||||
}
|
||||
|
||||
$originalfile = $this->get_file_summary($userservice, $source->id);
|
||||
$downloadlink = '';
|
||||
if (isset($originalfile->webContentLink)) {
|
||||
$downloadlink = $originalfile->webContentLink;
|
||||
} else if (isset($originalfile->webViewLink)) {
|
||||
$downloadlink = $originalfile->webViewLink;
|
||||
} else {
|
||||
// If we don't have a link, we cannot download the file.
|
||||
throw new repository_exception(
|
||||
'errorwhilecommunicatingwith',
|
||||
'repository',
|
||||
'',
|
||||
'Cannot download file: ' . $source->name
|
||||
);
|
||||
}
|
||||
|
||||
// Use the user service to download the file.
|
||||
$downloadedfile = $this->download_file(
|
||||
$userservice,
|
||||
$source->id,
|
||||
$downloadlink,
|
||||
$originalfile->name
|
||||
$originalfile->name,
|
||||
);
|
||||
// Upload the user file to the system drive.
|
||||
$uploaded = $this->upload_file(
|
||||
@@ -1068,7 +1056,7 @@ class repository_googledocs extends repository {
|
||||
$downloadedfile['path'],
|
||||
$downloadedfile['newfilename'],
|
||||
$source->exportformat,
|
||||
$parentid
|
||||
$parentid,
|
||||
);
|
||||
// Add the original file owner as a writer to the file.
|
||||
$this->add_writer_to_file($systemservice, $uploaded->id, $originalfile->owners[0]->emailAddress);
|
||||
@@ -1139,31 +1127,28 @@ class repository_googledocs extends repository {
|
||||
*
|
||||
* @param \repository_googledocs\rest $userservice The user service instance for Google Docs REST API.
|
||||
* @param string $fileid The ID of the file to download.
|
||||
* @param string $downloadlink The URL to the downloaded file.
|
||||
* @param string $originalfilename The file original name
|
||||
* @return array|repository_exception The downloaded file content or relevant response.
|
||||
*/
|
||||
protected function download_file(
|
||||
\repository_googledocs\rest $userservice,
|
||||
string $fileid,
|
||||
string $downloadlink,
|
||||
string $originalfilename
|
||||
): array|repository_exception {
|
||||
global $CFG;
|
||||
|
||||
// Ensure the file can be downloaded without credentials.
|
||||
$this->set_file_sharing_anyone_with_link_can_read($userservice, $fileid);
|
||||
$client = $this->get_user_oauth_client();
|
||||
$base = 'https://www.googleapis.com/drive/v3';
|
||||
$params = ['alt' => 'media'];
|
||||
$sourceurl = new moodle_url($base . '/files/' . $fileid, $params);
|
||||
|
||||
$tmp = make_request_directory();
|
||||
$temppath = $tmp . '/' . $fileid;
|
||||
$c = new curl();
|
||||
$options = ['filepath' => $temppath, 'timeout' => $CFG->repositorygetfiletimeout];
|
||||
$result = $c->download_one($downloadlink, null, $options);
|
||||
if ($result) {
|
||||
@chmod($temppath, $CFG->filepermissions);
|
||||
$path = $this->prepare_file($originalfilename);
|
||||
$options = ['filepath' => $path, 'timeout' => $CFG->repositorygetfiletimeout, 'followlocation' => true, 'maxredirs' => 5];
|
||||
$success = $client->download_one($sourceurl->out(false), null, $options);
|
||||
if ($success) {
|
||||
@chmod($path, $CFG->filepermissions);
|
||||
return [
|
||||
'path' => $temppath,
|
||||
'url' => $downloadlink,
|
||||
'path' => $path,
|
||||
'newfilename' => $originalfilename,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -49,64 +49,34 @@ if (!$repo) {
|
||||
$repo->check_capability();
|
||||
$repo->check_login();
|
||||
|
||||
$fs = get_file_storage();
|
||||
$usercontext = context_user::instance($USER->id);
|
||||
|
||||
switch ($action) {
|
||||
case 'upload':
|
||||
// Save the files in the draft area.
|
||||
$draftid = !empty($itemid) ? $itemid : file_get_unused_draft_itemid();
|
||||
$file = $_FILES['repo_upload_file'];
|
||||
|
||||
if (empty($file) || $file['error'] !== UPLOAD_ERR_OK) {
|
||||
echo json_encode(['error' => get_string('erroruploadfailed', 'repository')]);
|
||||
break;
|
||||
}
|
||||
|
||||
$filerecord = [
|
||||
'contextid' => $usercontext->id,
|
||||
'component' => 'user',
|
||||
'filearea' => 'draft',
|
||||
'itemid' => $draftid,
|
||||
'filepath' => '/',
|
||||
'filename' => clean_param($file['name'], PARAM_FILE),
|
||||
];
|
||||
|
||||
$fs->create_file_from_pathname($filerecord, $file['tmp_name']);
|
||||
|
||||
echo json_encode([
|
||||
'draftid' => $draftid,
|
||||
'file' => $filerecord['filename'],
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'commit':
|
||||
// Upload the files to Google Drive.
|
||||
if (empty($itemid)) {
|
||||
die(json_encode(['erroruploadfailed' => get_string('error', 'repository')]));
|
||||
}
|
||||
|
||||
// Grab files from draft area with the same itemid.
|
||||
$draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $itemid, "id", false);
|
||||
if (empty($draftfiles)) {
|
||||
die(json_encode(['erroruploadfailed' => get_string('error', 'repository')]));
|
||||
$files = $_FILES['files'];
|
||||
$tmp = make_request_directory();
|
||||
$savedfiles = [];
|
||||
if (is_array($files['name'])) {
|
||||
// Multiple files.
|
||||
foreach ($files['name'] as $idx => $name) {
|
||||
$dest = $tmp . '/' . basename($name);
|
||||
move_uploaded_file($files['tmp_name'][$idx], $dest);
|
||||
$savedfiles[] = $dest;
|
||||
}
|
||||
} else {
|
||||
// Single file.
|
||||
$dest = $tmp . '/' . basename($files['name']);
|
||||
move_uploaded_file($files['tmp_name'], $dest);
|
||||
$savedfiles[] = $dest;
|
||||
}
|
||||
|
||||
// Upload the file to Google Drive repository.
|
||||
$tmp = make_request_directory();
|
||||
$ha = new repository_googledocs($repoid, $context);
|
||||
$userauth = $ha->get_user_oauth_client();
|
||||
$userservice = new repository_googledocs\rest($userauth);
|
||||
foreach ($draftfiles as $draftfile) {
|
||||
$tempfile = $tmp . '/' . rand();
|
||||
$filename = $draftfile->get_filename();
|
||||
$draftfile->copy_content_to($tempfile);
|
||||
$ha->upload_file($userservice, $tempfile, $filename, 'download', "root");
|
||||
foreach ($savedfiles as $file) {
|
||||
$filename = basename($file);
|
||||
$ha->upload_file($userservice, $file, $filename, 'download', "root");
|
||||
}
|
||||
|
||||
// Clear drafts after upload them to Google drive.
|
||||
$fs->delete_area_files($usercontext->id, 'user', 'draft', $itemid);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
break;
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template repository_googledocs/upload_dialogue
|
||||
|
||||
Google repository upload dialogue.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
|
||||
}
|
||||
}}
|
||||
<div class="repository_googledocs_dropzone_container"></div>
|
||||
<div class="repository_googledocs_files_container">
|
||||
<h5>
|
||||
{{#str}} attachedfiles, repository {{/str}}
|
||||
</h5>
|
||||
<ul class="repository_googledocs_files_list"></ul>
|
||||
</div>
|
||||
Reference in New Issue
Block a user