Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
43 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
namespace local_listcoursefiles;
18
 
19
/**
20
 * Class course_file
21
 * @package local_listcoursefiles
22
 * @copyright  2017 Martin Gauk (@innoCampus, TU Berlin)
23
 * @author     Jeremy FitzPatrick
24
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25
 */
26
class course_file {
27
    /**
28
     * @var \stdClass
29
     */
30
    protected $file;
31
 
32
    /**
33
     * @var int
34
     */
35
    protected $courseid = 0;
36
 
37
    /* Properties used by the template. */
38
    /**
39
     * @var int
40
     */
41
    public $fileid = 0;
42
 
43
    /**
44
     * @var string
45
     */
46
    public $filelicense = '';
47
 
48
    /**
49
     * @var string Friendly readable size of the file (MB or kB as appropriate)
50
     */
51
    public $filesize = '';
52
 
53
    /**
54
     * @var string
55
     */
56
    public $filetype = '';
57
 
58
    /**
59
     * @var string The name of the person who uploaded the file.
60
     */
61
    public $fileuploader = '';
62
 
63
    /**
64
     * @var bool Is the license expired?
65
     */
66
    public $fileexpired = false;
67
 
68
    /**
69
     * @var false|string
70
     */
71
    public $fileurl = false;
72
 
73
    /**
74
     * @var string
75
     */
76
    public $filename = '';
77
 
78
    /**
79
     * @var false|string A link to the page where the file is used.
80
     */
81
    public $filecomponenturl = false;
82
 
83
    /**
84
     * @var string
85
     */
86
    public $filecomponent;
87
 
88
    /**
89
     * @var string|false A link to the page with the editor where the file was added.
90
     */
91
    public $fileediturl = false;
92
 
93
    /**
94
     * @var string A message stating if the file is used or unknown.
95
     */
96
    public $fileused;
97
 
98
    /**
99
     * Creates an object of this class or an appropriate subclass.
100
     * @param \stdClass $file
101
     * @return course_file
102
     * @throws \coding_exception
103
     * @throws \dml_exception
104
     * @throws \moodle_exception
105
     */
106
    public static function create(\stdClass $file): course_file {
107
        $classname = '\local_listcoursefiles\components\\' . $file->component;
108
        if (class_exists($classname)) {
109
            return new $classname($file);
110
        }
111
        return new course_file($file);
112
    }
113
 
114
    /**
115
     * course_file constructor.
116
     * @param \stdClass $file
117
     * @throws \coding_exception
118
     * @throws \dml_exception
119
     * @throws \moodle_exception
120
     */
121
    public function __construct(\stdClass $file) {
122
        global $COURSE;
123
        $this->courseid = $COURSE->id;
124
        $this->file = $file;
125
        $this->filelicense = licences::get_license_name_color($file->license ?? '');
126
        $this->fileid = $file->id;
127
        $this->filesize = display_size($file->filesize);
128
        $this->filetype = mimetypes::get_file_type_translation($file->mimetype);
129
        $this->fileuploader = fullname($file);
130
        $this->fileexpired = !$this->check_mimetype_license_expiry_date();
131
 
132
        $fileurl = $this->get_file_download_url();
133
        $this->fileurl = ($fileurl) ? $fileurl->out() : false;
134
        $this->filename = $this->get_displayed_filename();
135
 
136
        $componenturl = $this->get_component_url();
137
        $this->filecomponenturl = ($componenturl) ? $componenturl->out() : false;
138
        $this->filecomponent = course_files::get_component_translation($file->component);
139
 
140
        $isused = $this->is_file_used();
141
        if ($isused === true) {
142
            $this->fileused = get_string('yes', 'core');
143
        } else if ($isused === false) {
144
            $this->fileused = get_string('no', 'core');
145
        } else {
146
            $this->fileused = get_string('nottested', 'local_listcoursefiles');
147
        }
148
 
149
        $editurl = $this->get_edit_url();
150
        $this->fileediturl = ($editurl) ? $editurl->out(false) : false;
151
    }
152
 
153
    /**
154
     * Getter for filename
155
     * @return string
156
     */
157
    protected function get_displayed_filename(): string {
158
        return $this->file->filename;
159
    }
160
 
161
    /**
162
     * Check if a file with a specific license has expired.
163
     *
164
     * This checks if a file has been expired because:
165
     *  - it is a document (has a particular mimetype),
166
     *  - has been provided under a specific license
167
     *  - and the expiry date is exceed (in respect of the course start date and the file creation time).
168
     *
169
     * The following settings need to be defined in the config.php:
170
     *   array $CFG->fileexpirylicenses which licenses (shortnames) expire
171
     *   int $CFG->fileexpirydate when do files expire (unix time)
172
     *   array $CFG->filemimetypes['document'] mime types of documents
173
     *
174
     * These adjustments were made by Technische Universität Berlin in order to conform to § 52a UrhG.
175
     *
176
     * @return boolean whether file is allowed to be delivered to students
177
     */
178
    protected function check_mimetype_license_expiry_date(): bool {
179
        global $CFG, $COURSE;
180
 
181
        // Check if enabled/configured.
182
        if (!isset($CFG->fileexpirydate, $CFG->fileexpirylicenses, $CFG->filemimetypes['document'])) {
183
            return true;
184
        }
185
 
186
        if (in_array($this->file->license, $CFG->fileexpirylicenses)) {
187
            $isdoc = false;
188
            $fmimetype = $this->file->mimetype;
189
            foreach ($CFG->filemimetypes['document'] as $mime) {
190
                if ($mime === $fmimetype || (substr($mime, -1) === '%' && strncmp($mime, $fmimetype, strlen($mime) - 1) === 0)) {
191
                    $isdoc = true;
192
                    break;
193
                }
194
            }
195
            $coursestart = $COURSE->startdate ?? 0;
196
            if ($isdoc && $CFG->fileexpirydate > max($coursestart, $this->file->timecreated)) {
197
                return false;
198
            }
199
        }
200
 
201
        return true;
202
    }
203
 
204
    /**
205
     * Try to get the download url for a file.
206
     *
207
     * @return null|\moodle_url
208
     * @throws \moodle_exception
209
     */
210
    protected function get_file_download_url(): ?\moodle_url {
211
        if ($this->file->filearea == 'intro') {
212
            return $this->get_standard_file_download_url();
213
        }
214
        return null;
215
    }
216
 
217
    /**
218
     * Get the standard download url for a file.
219
     *
220
     * Most pluginfile urls are constructed the same way.
221
     *
222
     * @param bool $insertitemid
223
     * @return \moodle_url
224
     * @throws \moodle_exception
225
     */
226
    protected function get_standard_file_download_url(bool $insertitemid = true): \moodle_url {
227
        $url = '/pluginfile.php/' . $this->file->contextid . '/' . $this->file->component . '/' . $this->file->filearea;
228
        if ($insertitemid) {
229
            $url .= '/' . $this->file->itemid;
230
        }
231
        $url .= $this->file->filepath . $this->file->filename;
232
        return new \moodle_url($url);
233
    }
234
 
235
    /**
236
     * Try to get the url for the component (module or course).
237
     *
238
     * @return null|\moodle_url
239
     * @throws \moodle_exception
240
     */
241
    protected function get_component_url(): ?\moodle_url {
242
        if ($this->file->contextlevel == CONTEXT_MODULE) {
243
            $coursemodinfo = get_fast_modinfo($this->courseid);
244
            if (!empty($coursemodinfo->cms[$this->file->instanceid])) {
245
                return $coursemodinfo->cms[$this->file->instanceid]->url;
246
            }
247
        }
248
        return null;
249
    }
250
 
251
    /**
252
     * Checks if embedded files have been used
253
     *
254
     * @return bool|null
255
     * @throws \dml_exception
256
     */
257
    protected function is_file_used(): ?bool {
258
        global $DB;
259
        $component = strpos($this->file->component, 'mod_') === 0 ? 'mod' : $this->file->component;
260
        switch ($component) {
261
            case 'mod': // Course module.
262
                $modname = str_replace('mod_', '', $this->file->component);
263
                if (!array_key_exists($modname, \core_component::get_plugin_list('mod'))) {
264
                    return null;
265
                }
266
                if ($this->file->filearea === 'intro') {
267
                    $sql = "SELECT m.*
268
                              FROM {context} ctx
269
                              JOIN {course_modules} cm ON cm.id = ctx.instanceid
270
                              JOIN {{$modname}} m ON m.id = cm.instance
271
                             WHERE ctx.id = ?";
272
                    $mod = $DB->get_record_sql($sql, [$this->file->contextid]);
273
                    return $this->is_embedded_file_used($mod, 'intro', $this->file->filename);
274
                }
275
                break;
276
            case 'question':
277
                $question = $DB->get_record('question', ['id' => $this->file->itemid]);
278
                return $this->is_embedded_file_used($question, $this->file->filearea, $this->file->filename);
279
            case 'qtype_essay':
280
                $question = $DB->get_record('qtype_essay_options', ['questionid' => $this->file->itemid]);
281
                return $this->is_embedded_file_used($question, 'graderinfo', $this->file->filename);
282
        }
283
        return null;
284
    }
285
 
286
    /**
287
     * Test if a file is embedded in text
288
     *
289
     * @param \stdClass|false $record
290
     * @param string $field
291
     * @param string $filename
292
     * @return bool|null
293
     */
294
    protected function is_embedded_file_used($record, string $field, string $filename): ?bool {
295
        if ($record && property_exists($record, $field)) {
296
            return is_int(strpos($record->$field, '@@PLUGINFILE@@/' . rawurlencode($filename)));
297
        }
298
        return null;
299
    }
300
 
301
    /**
302
     * Creates the URL for the editor where the file is added
303
     *
304
     * @return \moodle_url|null
305
     * @throws \dml_exception
306
     * @throws \moodle_exception
307
     */
308
    protected function get_edit_url(): ?\moodle_url {
309
        global $DB;
310
        $component = strpos($this->file->component, 'mod_') === 0 ? 'mod' : $this->file->component;
311
        switch ($component) {
312
            case 'mod':
313
                if ($this->file->filearea === 'intro') { // Just checking description for now.
314
                    $sql = "SELECT cm.*
315
                              FROM {context} ctx
316
                              JOIN {course_modules} cm ON cm.id = ctx.instanceid
317
                             WHERE ctx.id = ?";
318
                    $mod = $DB->get_record_sql($sql, [$this->file->contextid]);
319
                    return new \moodle_url('/course/modedit.php?', ['update' => $mod->id]);
320
                }
321
                break;
322
            case 'question':
323
            case 'qtype_essay':
324
                return new \moodle_url('/question/question.php?', ['courseid' => $this->courseid, 'id' => $this->file->itemid]);
325
        }
326
        return null;
327
    }
328
}