Proyectos de Subversion Moodle

Rev

Autoría | Ultima modificación | Ver Log |

<?php
// 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/>.

/**
 * Implementation of the Amanote filter plugin.
 *
 * @package     filter_amanote
 * @copyright   2020 Amaplex Software
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */

defined('MOODLE_INTERNAL') || die;

require_once($CFG->libdir . '/externallib.php');
require_once(__DIR__ . '/helpers/filehelper.php');
require_once(__DIR__ . '/models/annotatable.php');

/**
 * Filter for processing file links for Amanote enhancements.
 *
 * @copyright  2020 Amaplex Software
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
class filter_amanote extends moodle_text_filter {
    /**
     * Set up the filter and insert JS scripts to page using amd.
     *
     * @param moodle_page $page The current page.
     * @param context $context The current context.
     */
    public function setup($page, $context) {
        try {
            global $PAGE, $COURSE;

            // Check if the filter is enabled for the current course.
            $enabledfilters = filter_get_active_in_context(context_course::instance($COURSE->id));
            if (!isset($enabledfilters['amanote'])) {
                return;
            }

            static $scriptinserted = false;

            // Insert script if needed.
            if ($scriptinserted ||
                (stripos($PAGE->pagetype, 'course-view') !== 0 && $PAGE->pagetype !== 'mod-folder-view') ||
                (strpos($PAGE->url, 'user/') !== false)) {
                return;
            }

            $this->insert_script($page);
            $scriptinserted = true;
        } catch (Exception $e) {
            debugging('An error occurred: ' . $e->getMessage(), DEBUG_DEVELOPER);
        }
    }

    /**
     * Insert the js script.
     *
     * @param moodle_page $page The page in which the script should be inserted.
     */
    private function insert_script($page) {
        global $CFG;

        $params = $this->generate_json_params();
        $userparams = $this->generate_json_user_params();

        // Insert user params using AMD.
        $page->requires->js_call_amd('filter_amanote/main', 'init', [$userparams]);

        // Insert params in footer (AMD can't handle long params).
        $script = <<<EOF
            <script>
                var amanote_params = $params;
            </script>
EOF;

        if (!isset($CFG->additionalhtmlfooter)) {
            $CFG->additionalhtmlfooter = '';
        }

        $CFG->additionalhtmlfooter .= $script;
    }

    /**
     * Return the Moodle params needed by the js script in JSON format.
     *
     * @return string The params in JSON string format.
     */
    private function generate_json_params() {
        global $USER, $COURSE, $CFG, $OUTPUT;

        try {
            $config = get_config('filter_amanote');
            $siteurl = $this->get_site_url();
            $language = substr($USER->lang, 0, 2);
            $usercontext = context_user::instance($USER->id);
            $privatefilepath = '/' . $usercontext->id . '/user/private/Amanote/';
            $contentkind = $config->anonymous ? 'document' : null;
            $annotatables = $this->get_annotatables($COURSE, $contentkind);
            $moodleversion = preg_replace('/(\d+\.\d+(\.\d+)?) .*$/', '$1', $CFG->release);
            $notelogo = $this->get_note_taking_logo_name($config->openingmode);
            $logourl = $OUTPUT->image_url($notelogo , 'filter_amanote')->__toString();
            $annotatedlogourl = $OUTPUT->image_url($notelogo . '-annotated', 'filter_amanote')->__toString();
            $savednotes = null;

            if ($config->saveinprivate) {
                $savednotes = get_user_notes_for_course($USER->id, $COURSE->id);
            }

            return json_encode([
                'siteURL' => $siteurl,
                'privateFilePath' => $privatefilepath,
                'savedNotes' => $savednotes,
                'annotatables' => $annotatables,
                'moodle' => [
                    'version' => $moodleversion,
                ],
                'plugin' => [
                    'version' => $config->version,
                    'saveInProvider' => ($config->saveinprivate == '1'),
                    'preventDownload' => ($config->preventdownload == '1'),
                    'openingMode' => $config->openingmode,
                    'target' => $config->target,
                    'key' => $config->key,
                    'anonymous' => ($config->anonymous == '1'),
                    'worksheet' => ($config->worksheet == '1'),
                    'logo' => $logourl,
                    'annotatedLogo' => $annotatedlogourl,
                ],
                'language' => $language,
                'strings' => [
                    'modalDescription' => get_string('modaldescription', 'filter_amanote'),
                    'annotateResource' => get_string('annotateresource', 'filter_amanote'),
                    'viewResource' => get_string('viewresource', 'filter_amanote'),
                    'downloadNotes' => get_string('downloadnotes', 'filter_amanote'),
                    'openAnalytics' => get_string('openanalytics', 'filter_amanote'),
                    'openPodcastCreator' => get_string('openpodcast', 'filter_amanote'),
                    'openStudentsWorks' => get_string('openstudentsworks', 'filter_amanote'),
                    'teacher' => get_string('teacher', 'filter_amanote'),
                    'deletefilewarning' => get_string('deletefilewarning', 'filter_amanote'),
                    'seeguide' => get_string('seeguide', 'filter_amanote'),
                    'stopmodal' => get_string('stopmodal', 'filter_amanote'),
                ],
            ]);
        } catch (Exception $e) {
            debugging('An error occurred: ' . $e->getMessage() . $e->getTraceAsString(), DEBUG_DEVELOPER);
        }
    }

    /**
     * Return the note-taking logo name for the given opening mode.
     *
     * @param integer $openingmode The opening mode.
     *
     * @return string The note-taking logo name.
     */
    private function get_note_taking_logo_name($openingmode) {
        $openingmodeicons = [
            '0' => 'amanote-logo',
            '1' => 'amanote-logo',
            '2' => 'note-icon',
            '3' => get_string('takenotesicon', 'filter_amanote'),
        ];

        return $openingmodeicons[$openingmode];
    }

    /**
     * Return the user params needed by the js script in JSON format.
     *
     * @return string The user params in JSON string format.
     */
    private function generate_json_user_params() {
        global $USER, $COURSE;

        $coursecontext = context_course::instance($COURSE->id, MUST_EXIST);
        $isteacher = has_capability('moodle/course:update', $coursecontext, $USER->id, false);
        $token = $this->get_current_user_token();

        return json_encode([
            'id' => $USER->id,
            'token' => [
                'value' => $token->token,
                'expiration' => $token->validuntil,
            ],
            'isTeacher' => $isteacher,
        ]);
    }

    /**
     * Return the token of the current user.
     *
     * @return token The user token.
     */
    private function get_current_user_token() {
        global $DB;

        $params = ['shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE, 'enabled' => 1];
        $service = $DB->get_record('external_services', $params);

        if (empty($service)) {
            return null;
        }

        return external_generate_token_for_current_user($service);
    }

    /**
     * Return the site url.
     *
     * @return string The site url (example: https://demo.moodle.com).
     */
    private function get_site_url() {
        global $CFG;

        // Check if protocol is HTTP.
        if (preg_match('/^http:\/\//', $CFG->wwwroot)) {

            $securewwwroot = preg_replace('/^http:\/\//', 'https://', $CFG->wwwroot, 1);

            // Check if Moodle site exists in HTTPS.
            $curl = curl_init($securewwwroot);
            if (curl_exec($curl)) {
                return $securewwwroot;
            }
            curl_close($curl);
        }

        return $CFG->wwwroot;
    }

    /**
     * Return all annotatables for the given course.
     *
     * @param course $course The course.
     * @param string $contentkind Get only a specific content type.
     *
     * @return array List of all annotatable for the given course.
     */
    private function get_annotatables($course, $contentkind = null) {
        global $DB;

        $annotatables = [];
        $supportedtypes = get_supported_mimetypes($contentkind);

        // Get all the annotable files for the given course.
        $sql = "SELECT
                    {files}.id as id,
                    {course_modules}.id as cmid,
                    {course_modules}.instance as modinstance,
                    {context}.id as contextid,
                    {files}.mimetype,
                    {files}.component,
                    {files}.filearea,
                    {files}.filepath,
                    {files}.filename
                FROM {course_modules}
                    LEFT JOIN {context} ON {context}.instanceid = {course_modules}.id
                    LEFT JOIN {files} ON {files}.contextid = {context}.id
                    AND {course_modules}.course = :courseid
                    WHERE {files}.component in ('mod_resource', 'mod_label', 'mod_folder')
                    AND {files}.source IS NOT NULL AND {files}.filename != '.'
                    ";

        $files = $DB->get_records_sql($sql, ['courseid' => $course->id]);

        if (!$files || count($files) <= 0) {
            return [];
        }

        foreach ($files as $file) {
            try {
                // Add only supported files.
                if (!in_array($file->mimetype, $supportedtypes)) {
                    continue;
                }

                $annotatable = get_annotatable_for_file($file, $course->id, $file->cmid, $file->modinstance);

                // Add the annotatable to the array of annotatables.
                array_push($annotatables, $annotatable);

            } catch (Exception $e) {
                debugging('An error occurred: ' . $e->getMessage(), DEBUG_DEVELOPER);
                continue;
            }
        }

        // Add the annotables for urls.
        $annotatables = array_merge($annotatables, $this->get_annotatable_urls($course, $contentkind));

        return $annotatables;
    }

    /**
     * Return all annotable urls for a given course.
     *
     * @param course $course The course.
     * @param string $contentkind Get only a specific content type.
     *
     * @return array List of annotable urls for the given course.
     */
    private function get_annotatable_urls($course, $contentkind = null) {
        global $DB;

        $annotatables = [];
        $supportedtypes = get_supported_mimetypes($contentkind);

        // Get the urls for the given course.
        $sql = "SELECT {course_modules}.id as cmid, {url}.externalurl FROM {url}
            LEFT JOIN {course_modules} ON {course_modules}.instance = {url}.id
            LEFT JOIN {modules} ON {modules}.id = {course_modules}.module
            WHERE {course_modules}.course = :courseid
            AND {modules}.name = 'url'";

        $urls = $DB->get_records_sql($sql, ['courseid' => $course->id]);

        if (!$urls || count($urls) <= 0) {
            return $annotatables;
        }

        foreach ($urls as $url) {
            try {
                // Add only supported files.
                $annotatable = get_annotatable_for_url($url, $course->id, $url->cmid);

                if (!$annotatable->mimetype || !in_array($annotatable->mimetype, $supportedtypes)) {
                    continue;
                }

                // Add the annotatable to the array of annotatables.
                array_push($annotatables, $annotatable);
            } catch (Exception $e) {
                debugging('An error occurred: ' . $e->getMessage(), DEBUG_DEVELOPER);
                continue;
            }
        }

        return $annotatables;
    }

    /**
     * Filters the given HTML text.
     *
     * @param string $text HTML to be processed.
     * @param array $options The options.
     *
     * @return string String containing processed HTML.
     */
    public function filter($text, array $options = []) {
        return $text;
    }
}