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
/**
18
 * Implementation of the Amanote filter plugin.
19
 *
20
 * @package     filter_amanote
21
 * @copyright   2020 Amaplex Software
22
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
defined('MOODLE_INTERNAL') || die;
26
 
27
require_once($CFG->libdir . '/externallib.php');
28
require_once(__DIR__ . '/helpers/filehelper.php');
29
require_once(__DIR__ . '/models/annotatable.php');
30
 
31
/**
32
 * Filter for processing file links for Amanote enhancements.
33
 *
34
 * @copyright  2020 Amaplex Software
35
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36
 */
37
class filter_amanote extends moodle_text_filter {
38
    /**
39
     * Set up the filter and insert JS scripts to page using amd.
40
     *
41
     * @param moodle_page $page The current page.
42
     * @param context $context The current context.
43
     */
44
    public function setup($page, $context) {
45
        try {
46
            global $PAGE, $COURSE;
47
 
48
            // Check if the filter is enabled for the current course.
49
            $enabledfilters = filter_get_active_in_context(context_course::instance($COURSE->id));
50
            if (!isset($enabledfilters['amanote'])) {
51
                return;
52
            }
53
 
54
            static $scriptinserted = false;
55
 
56
            // Insert script if needed.
57
            if ($scriptinserted ||
58
                (stripos($PAGE->pagetype, 'course-view') !== 0 && $PAGE->pagetype !== 'mod-folder-view') ||
59
                (strpos($PAGE->url, 'user/') !== false)) {
60
                return;
61
            }
62
 
63
            $this->insert_script($page);
64
            $scriptinserted = true;
65
        } catch (Exception $e) {
66
            debugging('An error occurred: ' . $e->getMessage(), DEBUG_DEVELOPER);
67
        }
68
    }
69
 
70
    /**
71
     * Insert the js script.
72
     *
73
     * @param moodle_page $page The page in which the script should be inserted.
74
     */
75
    private function insert_script($page) {
76
        global $CFG;
77
 
78
        $params = $this->generate_json_params();
79
        $userparams = $this->generate_json_user_params();
80
 
81
        // Insert user params using AMD.
82
        $page->requires->js_call_amd('filter_amanote/main', 'init', [$userparams]);
83
 
84
        // Insert params in footer (AMD can't handle long params).
85
        $script = <<<EOF
86
            <script>
87
                var amanote_params = $params;
88
            </script>
89
EOF;
90
 
91
        if (!isset($CFG->additionalhtmlfooter)) {
92
            $CFG->additionalhtmlfooter = '';
93
        }
94
 
95
        $CFG->additionalhtmlfooter .= $script;
96
    }
97
 
98
    /**
99
     * Return the Moodle params needed by the js script in JSON format.
100
     *
101
     * @return string The params in JSON string format.
102
     */
103
    private function generate_json_params() {
104
        global $USER, $COURSE, $CFG, $OUTPUT;
105
 
106
        try {
107
            $config = get_config('filter_amanote');
108
            $siteurl = $this->get_site_url();
109
            $language = substr($USER->lang, 0, 2);
110
            $usercontext = context_user::instance($USER->id);
111
            $privatefilepath = '/' . $usercontext->id . '/user/private/Amanote/';
112
            $contentkind = $config->anonymous ? 'document' : null;
113
            $annotatables = $this->get_annotatables($COURSE, $contentkind);
114
            $moodleversion = preg_replace('/(\d+\.\d+(\.\d+)?) .*$/', '$1', $CFG->release);
115
            $notelogo = $this->get_note_taking_logo_name($config->openingmode);
116
            $logourl = $OUTPUT->image_url($notelogo , 'filter_amanote')->__toString();
117
            $annotatedlogourl = $OUTPUT->image_url($notelogo . '-annotated', 'filter_amanote')->__toString();
118
            $savednotes = null;
119
 
120
            if ($config->saveinprivate) {
121
                $savednotes = get_user_notes_for_course($USER->id, $COURSE->id);
122
            }
123
 
124
            return json_encode([
125
                'siteURL' => $siteurl,
126
                'privateFilePath' => $privatefilepath,
127
                'savedNotes' => $savednotes,
128
                'annotatables' => $annotatables,
129
                'moodle' => [
130
                    'version' => $moodleversion,
131
                ],
132
                'plugin' => [
133
                    'version' => $config->version,
134
                    'saveInProvider' => ($config->saveinprivate == '1'),
135
                    'preventDownload' => ($config->preventdownload == '1'),
136
                    'openingMode' => $config->openingmode,
137
                    'target' => $config->target,
138
                    'key' => $config->key,
139
                    'anonymous' => ($config->anonymous == '1'),
140
                    'worksheet' => ($config->worksheet == '1'),
141
                    'logo' => $logourl,
142
                    'annotatedLogo' => $annotatedlogourl,
143
                ],
144
                'language' => $language,
145
                'strings' => [
146
                    'modalDescription' => get_string('modaldescription', 'filter_amanote'),
147
                    'annotateResource' => get_string('annotateresource', 'filter_amanote'),
148
                    'viewResource' => get_string('viewresource', 'filter_amanote'),
149
                    'downloadNotes' => get_string('downloadnotes', 'filter_amanote'),
150
                    'openAnalytics' => get_string('openanalytics', 'filter_amanote'),
151
                    'openPodcastCreator' => get_string('openpodcast', 'filter_amanote'),
152
                    'openStudentsWorks' => get_string('openstudentsworks', 'filter_amanote'),
153
                    'teacher' => get_string('teacher', 'filter_amanote'),
154
                    'deletefilewarning' => get_string('deletefilewarning', 'filter_amanote'),
155
                    'seeguide' => get_string('seeguide', 'filter_amanote'),
156
                    'stopmodal' => get_string('stopmodal', 'filter_amanote'),
157
                ],
158
            ]);
159
        } catch (Exception $e) {
160
            debugging('An error occurred: ' . $e->getMessage() . $e->getTraceAsString(), DEBUG_DEVELOPER);
161
        }
162
    }
163
 
164
    /**
165
     * Return the note-taking logo name for the given opening mode.
166
     *
167
     * @param integer $openingmode The opening mode.
168
     *
169
     * @return string The note-taking logo name.
170
     */
171
    private function get_note_taking_logo_name($openingmode) {
172
        $openingmodeicons = [
173
            '0' => 'amanote-logo',
174
            '1' => 'amanote-logo',
175
            '2' => 'note-icon',
176
            '3' => get_string('takenotesicon', 'filter_amanote'),
177
        ];
178
 
179
        return $openingmodeicons[$openingmode];
180
    }
181
 
182
    /**
183
     * Return the user params needed by the js script in JSON format.
184
     *
185
     * @return string The user params in JSON string format.
186
     */
187
    private function generate_json_user_params() {
188
        global $USER, $COURSE;
189
 
190
        $coursecontext = context_course::instance($COURSE->id, MUST_EXIST);
191
        $isteacher = has_capability('moodle/course:update', $coursecontext, $USER->id, false);
192
        $token = $this->get_current_user_token();
193
 
194
        return json_encode([
195
            'id' => $USER->id,
196
            'token' => [
197
                'value' => $token->token,
198
                'expiration' => $token->validuntil,
199
            ],
200
            'isTeacher' => $isteacher,
201
        ]);
202
    }
203
 
204
    /**
205
     * Return the token of the current user.
206
     *
207
     * @return token The user token.
208
     */
209
    private function get_current_user_token() {
210
        global $DB;
211
 
212
        $params = ['shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE, 'enabled' => 1];
213
        $service = $DB->get_record('external_services', $params);
214
 
215
        if (empty($service)) {
216
            return null;
217
        }
218
 
219
        return external_generate_token_for_current_user($service);
220
    }
221
 
222
    /**
223
     * Return the site url.
224
     *
225
     * @return string The site url (example: https://demo.moodle.com).
226
     */
227
    private function get_site_url() {
228
        global $CFG;
229
 
230
        // Check if protocol is HTTP.
231
        if (preg_match('/^http:\/\//', $CFG->wwwroot)) {
232
 
233
            $securewwwroot = preg_replace('/^http:\/\//', 'https://', $CFG->wwwroot, 1);
234
 
235
            // Check if Moodle site exists in HTTPS.
236
            $curl = curl_init($securewwwroot);
237
            if (curl_exec($curl)) {
238
                return $securewwwroot;
239
            }
240
            curl_close($curl);
241
        }
242
 
243
        return $CFG->wwwroot;
244
    }
245
 
246
    /**
247
     * Return all annotatables for the given course.
248
     *
249
     * @param course $course The course.
250
     * @param string $contentkind Get only a specific content type.
251
     *
252
     * @return array List of all annotatable for the given course.
253
     */
254
    private function get_annotatables($course, $contentkind = null) {
255
        global $DB;
256
 
257
        $annotatables = [];
258
        $supportedtypes = get_supported_mimetypes($contentkind);
259
 
260
        // Get all the annotable files for the given course.
261
        $sql = "SELECT
262
                    {files}.id as id,
263
                    {course_modules}.id as cmid,
264
                    {course_modules}.instance as modinstance,
265
                    {context}.id as contextid,
266
                    {files}.mimetype,
267
                    {files}.component,
268
                    {files}.filearea,
269
                    {files}.filepath,
270
                    {files}.filename
271
                FROM {course_modules}
272
                    LEFT JOIN {context} ON {context}.instanceid = {course_modules}.id
273
                    LEFT JOIN {files} ON {files}.contextid = {context}.id
274
                    AND {course_modules}.course = :courseid
275
                    WHERE {files}.component in ('mod_resource', 'mod_label', 'mod_folder')
276
                    AND {files}.source IS NOT NULL AND {files}.filename != '.'
277
                    ";
278
 
279
        $files = $DB->get_records_sql($sql, ['courseid' => $course->id]);
280
 
281
        if (!$files || count($files) <= 0) {
282
            return [];
283
        }
284
 
285
        foreach ($files as $file) {
286
            try {
287
                // Add only supported files.
288
                if (!in_array($file->mimetype, $supportedtypes)) {
289
                    continue;
290
                }
291
 
292
                $annotatable = get_annotatable_for_file($file, $course->id, $file->cmid, $file->modinstance);
293
 
294
                // Add the annotatable to the array of annotatables.
295
                array_push($annotatables, $annotatable);
296
 
297
            } catch (Exception $e) {
298
                debugging('An error occurred: ' . $e->getMessage(), DEBUG_DEVELOPER);
299
                continue;
300
            }
301
        }
302
 
303
        // Add the annotables for urls.
304
        $annotatables = array_merge($annotatables, $this->get_annotatable_urls($course, $contentkind));
305
 
306
        return $annotatables;
307
    }
308
 
309
    /**
310
     * Return all annotable urls for a given course.
311
     *
312
     * @param course $course The course.
313
     * @param string $contentkind Get only a specific content type.
314
     *
315
     * @return array List of annotable urls for the given course.
316
     */
317
    private function get_annotatable_urls($course, $contentkind = null) {
318
        global $DB;
319
 
320
        $annotatables = [];
321
        $supportedtypes = get_supported_mimetypes($contentkind);
322
 
323
        // Get the urls for the given course.
324
        $sql = "SELECT {course_modules}.id as cmid, {url}.externalurl FROM {url}
325
            LEFT JOIN {course_modules} ON {course_modules}.instance = {url}.id
326
            LEFT JOIN {modules} ON {modules}.id = {course_modules}.module
327
            WHERE {course_modules}.course = :courseid
328
            AND {modules}.name = 'url'";
329
 
330
        $urls = $DB->get_records_sql($sql, ['courseid' => $course->id]);
331
 
332
        if (!$urls || count($urls) <= 0) {
333
            return $annotatables;
334
        }
335
 
336
        foreach ($urls as $url) {
337
            try {
338
                // Add only supported files.
339
                $annotatable = get_annotatable_for_url($url, $course->id, $url->cmid);
340
 
341
                if (!$annotatable->mimetype || !in_array($annotatable->mimetype, $supportedtypes)) {
342
                    continue;
343
                }
344
 
345
                // Add the annotatable to the array of annotatables.
346
                array_push($annotatables, $annotatable);
347
            } catch (Exception $e) {
348
                debugging('An error occurred: ' . $e->getMessage(), DEBUG_DEVELOPER);
349
                continue;
350
            }
351
        }
352
 
353
        return $annotatables;
354
    }
355
 
356
    /**
357
     * Filters the given HTML text.
358
     *
359
     * @param string $text HTML to be processed.
360
     * @param array $options The options.
361
     *
362
     * @return string String containing processed HTML.
363
     */
364
    public function filter($text, array $options = []) {
365
        return $text;
366
    }
367
}