Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
/**
17
 * Contains the import_strategy_file class.
18
 *
19
 * @package tool_moodlenet
20
 * @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
21
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22
 */
23
namespace tool_moodlenet\local;
24
 
25
use core\antivirus\manager as avmanager;
26
 
27
/**
28
 * The import_strategy_file class.
29
 *
30
 * The import_strategy_file objects contains the setup steps needed to prepare a resource for import as a file into Moodle. This
31
 * ensures the remote_resource is first downloaded and put in a draft file area, ready for use as a file by the handling module.
32
 *
33
 * @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
34
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35
 */
36
class import_strategy_file implements import_strategy {
37
 
38
    /**
39
     * Get an array of import_handler_info objects representing modules supporting import of this file type.
40
     *
41
     * @param array $registrydata the fully populated registry.
42
     * @param remote_resource $resource the remote resource.
43
     * @return import_handler_info[] the array of import_handler_info objects.
44
     */
45
    public function get_handlers(array $registrydata, remote_resource $resource): array {
46
        $handlers = [];
47
        foreach ($registrydata['files'] as $index => $items) {
48
            foreach ($items as $item) {
49
                if ($index === $resource->get_extension() || $index === '*') {
50
                    $handlers[] = new import_handler_info($item['module'], $item['message'], $this);
51
                }
52
            }
53
        }
54
        return $handlers;
55
    }
56
 
57
    /**
58
     * Import the remote resource according to the rules of this strategy.
59
     *
60
     * @param remote_resource $resource the resource to import.
61
     * @param \stdClass $user the user to import on behalf of.
62
     * @param \stdClass $course the course into which the remote_resource is being imported.
63
     * @param int $section the section into which the remote_resource is being imported.
64
     * @return \stdClass the module data.
65
     * @throws \moodle_exception if the file size means the upload limit is exceeded for the user.
66
     */
67
    public function import(remote_resource $resource, \stdClass $user, \stdClass $course, int $section): \stdClass {
68
        // Before starting a potentially lengthy download, try to ensure the file size does not exceed the upload size restrictions
69
        // for the user. This is a time saving measure.
70
        // This is a naive check, that serves only to catch files if they provide the content length header.
71
        // Because of potential content encoding (compression), the stored file will be checked again after download as well.
72
        $size = $resource->get_download_size() ?? -1;
73
        $useruploadlimit = $this->get_user_upload_limit($user, $course);
74
        if ($this->size_exceeds_upload_limit($size, $useruploadlimit)) {
75
            throw new \moodle_exception('uploadlimitexceeded', 'tool_moodlenet', '', ['filesize' => $size,
76
                'uploadlimit' => $useruploadlimit]);
77
        }
78
 
79
        // Download the file into a request directory and scan it.
80
        [$filepath, $filename] = $resource->download_to_requestdir();
81
        avmanager::scan_file($filepath, $filename, true);
82
 
83
        // Check the final size of file against the user upload limits.
84
        $localsize = filesize(sprintf('%s/%s', $filepath, $filename));
85
        if ($this->size_exceeds_upload_limit($localsize, $useruploadlimit)) {
86
            throw new \moodle_exception('uploadlimitexceeded', 'tool_moodlenet', '', ['filesize' => $localsize,
87
                'uploadlimit' => $useruploadlimit]);
88
        }
89
 
90
        // Store in the user draft file area.
91
        $storedfile = $this->create_user_draft_stored_file($user, $filename, $filepath);
92
 
93
        // Prepare the data to be sent to the modules dndupload_handle hook.
94
        return $this->prepare_module_data($course, $resource, $storedfile->get_itemid());
95
    }
96
 
97
 
98
    /**
99
     * Creates the data to pass to the dndupload_handle() hooks.
100
     *
101
     * @param \stdClass $course the course record.
102
     * @param remote_resource $resource the resource being imported as a file.
103
     * @param int $draftitemid the itemid of the draft file.
104
     * @return \stdClass the data object.
105
     */
106
    protected function prepare_module_data(\stdClass $course, remote_resource $resource, int $draftitemid): \stdClass {
107
        $data = new \stdClass();
108
        $data->type = 'Files';
109
        $data->course = $course;
110
        $data->draftitemid = $draftitemid;
111
        $data->displayname = $resource->get_name();
112
        return $data;
113
    }
114
 
115
    /**
116
     * Get the max file size limit for the user in the course.
117
     *
118
     * @param \stdClass $user the user to check.
119
     * @param \stdClass $course the course to check in.
120
     * @return int the file size limit, in bytes.
121
     */
122
    protected function get_user_upload_limit(\stdClass $user, \stdClass $course): int {
123
        return get_user_max_upload_file_size(\context_course::instance($course->id), get_config('core', 'maxbytes'),
124
            $course->maxbytes, 0, $user);
125
    }
126
 
127
    /**
128
     * Does the size exceed the upload limit for the current import, taking into account user and core settings.
129
     *
130
     * @param int $sizeinbytes the size, in bytes.
131
     * @param int $useruploadlimit the upload limit, in bytes.
132
     * @return bool true if exceeded, false otherwise.
133
     * @throws \dml_exception
134
     */
135
    protected function size_exceeds_upload_limit(int $sizeinbytes, int $useruploadlimit): bool {
136
        if ($useruploadlimit != USER_CAN_IGNORE_FILE_SIZE_LIMITS && $sizeinbytes > $useruploadlimit) {
137
            return true;
138
        }
139
        return false;
140
    }
141
 
142
    /**
143
     * Create a file in the user drafts ready for use by plugins implementing dndupload_handle().
144
     *
145
     * @param \stdClass $user the user object.
146
     * @param string $filename the name of the file on disk
147
     * @param string $path the path where the file is stored on disk
148
     * @return \stored_file
149
     */
150
    protected function create_user_draft_stored_file(\stdClass $user, string $filename, string $path): \stored_file {
151
        global $CFG;
152
 
153
        $record = new \stdClass();
154
        $record->filearea = 'draft';
155
        $record->component = 'user';
156
        $record->filepath = '/';
157
        $record->itemid   = file_get_unused_draft_itemid();
158
        $record->license  = $CFG->sitedefaultlicense;
159
        $record->author   = '';
160
        $record->filename = clean_param($filename, PARAM_FILE);
161
        $record->contextid = \context_user::instance($user->id)->id;
162
        $record->userid = $user->id;
163
 
164
        $fullpathwithname = sprintf('%s/%s', $path, $filename);
165
 
166
        $fs = get_file_storage();
167
 
168
        return  $fs->create_file_from_pathname($record, $fullpathwithname);
169
    }
170
}