Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
// This file is part of Moodle - http://moodle.org/
2
//
3
// Moodle is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, either version 3 of the License, or
6
// (at your option) any later version.
7
//
8
// Moodle is distributed in the hope that it will be useful,
9
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
// GNU General Public License for more details.
12
//
13
// You should have received a copy of the GNU General Public License
14
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
15
 
16
/**
17
 * Tiny Media plugin for Moodle.
18
 *
19
 * @module      editor_tiny/uploader
20
 * @copyright   2022 Andrew Lyons <andrew@nicols.co.uk>
21
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22
 */
23
import {
24
    notifyUploadStarted,
25
    notifyUploadCompleted,
26
} from 'core_form/events';
27
import {getFilePicker} from 'editor_tiny/options';
28
 
29
// This image uploader is based on advice given at:
30
// https://www.tiny.cloud/docs/tinymce/6/upload-images/
31
export default (editor, filePickerType, blob, fileName, progress) => new Promise((resolve, reject) => {
32
    notifyUploadStarted(editor.targetElm.id);
33
 
34
    const xhr = new XMLHttpRequest();
35
 
36
    // Add the progress handler.
37
    xhr.upload.addEventListener('progress', (e) => {
38
        progress(e.loaded / e.total * 100);
39
    });
40
 
41
    xhr.addEventListener('load', () => {
42
        if (xhr.status === 403) {
43
            reject({
44
                message: `HTTP error: ${xhr.status}`,
45
                remove: true,
46
            });
47
            return;
48
        }
49
 
50
        if (xhr.status < 200 || xhr.status >= 300) {
51
            reject(`HTTP Error: ${xhr.status}`);
52
            return;
53
        }
54
 
55
        const response = JSON.parse(xhr.responseText);
56
 
57
        if (!response) {
58
            reject(`Invalid JSON: ${xhr.responseText}`);
59
            return;
60
        }
61
 
62
        notifyUploadCompleted(editor.targetElm.id);
63
 
64
        let location;
65
        if (response.url) {
66
            location = response.url;
67
        } else if (response.event && response.event === 'fileexists' && response.newfile) {
68
            // A file with this name is already in use here - rename to avoid conflict.
69
            // Chances are, it's a different image (stored in a different folder on the user's computer).
70
            // If the user wants to reuse an existing image, they can copy/paste it within the editor.
71
            location = response.newfile.url;
72
        }
73
 
74
        if (location && typeof location === 'string') {
75
            resolve(location);
76
            return;
77
        }
78
 
79
        // Try to parse the error response into a JSON object.
80
        const errorString = xhr.responseText;
81
        let output = '';
82
        try {
83
            output = JSON.parse(errorString);
84
        } catch (error) {
85
            // If the JSON parsing process returns an error, then it returns the original.
86
            output = errorString;
87
        }
88
 
89
        reject(output);
90
    });
91
 
92
    xhr.addEventListener('error', () => {
93
        reject({
94
            message: `Upload failed due to an XHR transport error. Code: ${xhr.status}`,
95
            remove: true,
96
        });
97
    });
98
 
99
    const formData = new FormData();
100
    const options = getFilePicker(editor, filePickerType);
101
 
102
    formData.append('repo_upload_file', blob, fileName);
103
    formData.append('itemid', options.itemid);
104
    Object.values(options.repositories).some((repository) => {
105
        if (repository.type === 'upload') {
106
            formData.append('repo_id', repository.id);
107
            return true;
108
        }
109
        return false;
110
    });
111
 
112
    formData.append('env', options.env);
113
    formData.append('sesskey', M.cfg.sesskey);
114
    formData.append('client_id', options.client_id);
115
    formData.append('savepath', options.savepath ?? '/');
116
    formData.append('ctx_id', options.context.id);
117
 
118
    // Accepted types can be either a string or an array, but an array is
119
    // expected in the processing script, so make sure we are sending an array.
120
    const acceptedTypes = options.accepted_types;
121
    if (Array.isArray(acceptedTypes)) {
122
        acceptedTypes.forEach(function(type) {
123
              formData.append('accepted_types[]', type);
124
        });
125
    } else {
126
        formData.append('accepted_types[]', acceptedTypes);
127
    }
128
 
129
    xhr.open('POST', `${M.cfg.wwwroot}/repository/repository_ajax.php?action=upload`, true);
130
    xhr.send(formData);
131
});