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

declare(strict_types=1);

namespace mod_edusharing;

use cached_cm_info;
use coding_exception;
use context_course;
use context_system;
use dml_exception;
use DOMDocument;
use Exception;
use stdClass;

/**
 * Class UtilityFunctions
 *
 * @author Marian Ziegler <ziegler@edu-sharing.net>
 * @package mod_edusharing
 */
class UtilityFunctions {
    /**
     * @var AppConfig|null
     */
    private ?AppConfig $appconfig;

    /**
     * UtilityFunctions constructor
     *
     * @param AppConfig|null $config
     */
    public function __construct(?AppConfig $config = null) {
        $this->appconfig = $config;
        $this->init();
    }

    /**
     * Function init
     *
     * @return void
     */
    private function init(): void {
        if ($this->appconfig === null) {
            $this->appconfig = new DefaultAppConfig();
        }
    }

    /**
     * Function get_object_id_from_url
     *
     * Get the object-id from object-url.
     * E.g. "abc-123-xyz-456789" for "ccrep://homeRepository/abc-123-xyz-456789"
     *
     * @param string $url
     * @return string
     */
    public function get_object_id_from_url(string $url): string {
        $objectid = parse_url($url, PHP_URL_PATH);
        if ($objectid === false) {
            try {
                trigger_error(get_string('error_get_object_id_from_url', 'edusharing'), E_USER_WARNING);
            } catch (Exception $exception) {
                unset($exception);
                trigger_error('error_get_object_id_from_url', E_USER_WARNING);
            }
            return '';
        }

        return str_replace('/', '', $objectid);
    }

    /**
     * Function get_repository_id_from_url
     *
     * Get the repository-id from object-url.
     * E.g. "homeRepository" for "ccrep://homeRepository/abc-123-xyz-456789"
     *
     * @param string $url
     * @return string
     * @throws Exception
     */
    public function get_repository_id_from_url(string $url): string {
        $repoid = parse_url($url, PHP_URL_HOST);
        if ($repoid === false) {
            throw new Exception(get_string('error_get_repository_id_from_url', 'edusharing'));
        }

        return $repoid;
    }

    /**
     * Functions get_redirect_url
     *
     * @param stdClass $edusharing
     * @param string $displaymode
     * @return string
     * @throws coding_exception
     * @throws dml_exception
     */
    public function get_redirect_url(
        stdClass $edusharing,
        string $displaymode = Constants::EDUSHARING_DISPLAY_MODE_DISPLAY
    ): string {
        global $USER;
        $url = rtrim($this->get_config_entry('application_cc_gui_url'), '/');
        $url .= '/renderingproxy';
        $url .= '?app_id=' . urlencode($this->get_config_entry('application_appid'));
        $url .= '&session=' . urlencode(session_id());
        try {
            $repoid = $this->get_repository_id_from_url($edusharing->object_url);
        } catch (Exception $exception) {
            debugging($exception->getMessage());
            return '';
        }
        $url     .= '&rep_id=' . urlencode($repoid);
        $url     .= '&obj_id=' . urlencode($this->get_object_id_from_url($edusharing->object_url));
        $url     .= '&resource_id=' . urlencode($edusharing->id);
        $url     .= '&course_id=' . urlencode($edusharing->course);
        $context = context_course::instance($edusharing->course);
        $roles   = get_user_roles($context, $USER->id);
        foreach ($roles as $role) {
            $url .= '&role=' . urlencode($role->shortname);
        }
        $url .= '&display=' . urlencode($displaymode);
        $url .= '&version=' . urlencode($edusharing->object_version);
        $url .= '&locale=' . urlencode(current_language());
        $url .= '&language=' . urlencode(current_language());
        $url .= '&u=' . rawurlencode(base64_encode($this->encrypt_with_repo_key($this->get_auth_key())));

        return $url;
    }

    /**
     * Function get_auth_key
     *
     * @throws dml_exception
     */
    public function get_auth_key(): string {
        global $USER, $SESSION;

        // Set by external sso script.
        if (!empty($SESSION->edusharing_sso) && $this->get_config_entry('obfuscate_auth_param') === '1') {
            return $SESSION->edusharing_sso[$this->get_config_entry('EDU_AUTH_PARAM_NAME_USERID')];
        }
        $guestoption = $this->get_config_entry('edu_guest_option');
        if (!empty($guestoption)) {
            $guestid = $this->get_config_entry('edu_guest_guest_id');

            return !empty($guestid) ? $guestid : 'esguest';
        }
        $eduauthkey = $this->get_config_entry('EDU_AUTH_KEY');
        if ($eduauthkey == 'id') {
            return $USER->id;
        }
        if ($eduauthkey == 'idnumber') {
            return $USER->idnumber;
        }
        if ($eduauthkey == 'email') {
            return $USER->email;
        }
        if (isset($USER->profile[$eduauthkey])) {
            return $USER->profile[$eduauthkey];
        }
        return $USER->username . $this->get_config_entry('auth_suffix');
    }

    /**
     * Function encrypt_with_repo_key
     *
     * @param string $data
     * @return string
     * @throws coding_exception
     * @throws dml_exception
     */
    public function encrypt_with_repo_key(string $data): string {
        $encrypted = '';
        $key       = openssl_get_publickey($this->get_config_entry('repository_public_key'));
        if (!openssl_public_encrypt($data, $encrypted, $key)) {
            trigger_error(get_string('error_encrypt_with_repo_public', 'edusharing'), E_USER_WARNING);
            return '';
        }
        return $encrypted;
    }

    /**
     * Function set_moodle_ids_in_edusharing_entries
     *
     * @param string $text
     * @param int $sectionid
     * @param int $moduleid
     *
     * @throws dml_exception
     */
    public function set_moodle_ids_in_edusharing_entries(string $text, int $sectionid, int $moduleid = 0): void {
        global $DB;
        $esmatches = $this->get_inline_object_matches($text);
        foreach ($esmatches as $match) {
            $resourceid = $this->get_resource_id_from_match($match);
            $edusharing = $DB->get_record('edusharing', ['id' => $resourceid], '*', MUST_EXIST);
            $edusharing->section_id = $sectionid;
            if ($moduleid !== 0) {
                $edusharing->module_id = $moduleid;
            }
            $DB->update_record('edusharing', $edusharing);
        }
    }

    /**
     * Function get_resource_id_from_match
     *
     * @param string $match
     * @return string
     */
    public function get_resource_id_from_match(string $match): string {
        $resourceid = '';
        $pos        = strpos($match, 'resourceid="');
        $offset     = 12;
        if ($pos === false) {
            $pos = strpos($match, "resourceId=");
            $offset = 11;
        }
        if ($pos !== false) {
            $resourceid = substr($match, $pos + $offset);
            $resourceid = substr($resourceid, 0, strpos($resourceid, "&"));
        }
        return $resourceid;
    }

    /**
     * Function update_settings_images
     *
     * @param string $settingname
     * @return void
     */
    public function update_settings_images(string $settingname): void {
        global $CFG;
        // The setting name that was updated comes as a string like 's_theme_photo_loginbackgroundimage'.
        // We split it on '_' characters.
        $parts = explode('_', $settingname);
        // And get the last one to get the setting name..
        $settingname = end($parts);
        // Admin settings are stored in system context.
        try {
            $syscontext = context_system::instance();
            $filename   = $this->get_config_entry($settingname);
        } catch (Exception $exception) {
            debugging($exception->getMessage());
            return;
        }
        // This is the value of the admin setting which is the filename of the uploaded file.
        // We extract the file extension because we want to preserve it.
        $extension = substr($filename, strrpos($filename, '.') + 1);
        // This is the path in the moodle internal file system.
        $fullpath = "/{$syscontext->id}/" . 'edusharing' . "/{$settingname}/0{$filename}";
        // Get an instance of the moodle file storage.
        $fs = get_file_storage();
        // This is an efficient way to get a file if we know the exact path.
        if ($file = $fs->get_file_by_hash(sha1($fullpath))) {
            // We got the stored file - copy it to data root.
            // This location matches the searched for location in theme_config::resolve_image_location.
            $pathname = $CFG->dataroot . '/pix_plugins/mod/edusharing/icon.' . $extension;
            // This pattern matches any previous files with maybe different file extensions.
            $pathpattern = $CFG->dataroot . '/pix_plugins/mod/edusharing/icon.*';
            // Make sure this dir exists.
            @mkdir($CFG->dataroot . '/pix_plugins/mod/edusharing/', $CFG->directorypermissions, true);
            // Delete any existing files for this setting.
            foreach (glob($pathpattern) as $filename) {
                @unlink($filename);
            }
            // Copy the current file to this location.
            $file->copy_content_to($pathname);
        } else {
            $pathpattern = $CFG->dataroot . '/pix_plugins/mod/edusharing/icon.*';
            // Make sure this dir exists.
            @mkdir($CFG->dataroot . '/pix_plugins/mod/edusharing/', $CFG->directorypermissions, true);
            // Delete any existing files for this setting.
            foreach (glob($pathpattern) as $filename) {
                @unlink($filename);
            }
        }
        // Reset theme caches.
        theme_reset_all_caches();
    }

    /**
     * Function get_course_module_info
     *
     * @param stdClass $coursemodule
     * @return cached_cm_info|bool
     */
    public function get_course_module_info(stdClass $coursemodule): cached_cm_info|bool {
        global $DB;
        try {
            $edusharing = $DB->get_record(
                'edusharing',
                ['id' => $coursemodule->instance],
                'id, name, intro, introformat',
                MUST_EXIST
            );
        } catch (Exception $exception) {
            debugging($exception->getMessage());
            return false;
        }
        $info = new cached_cm_info();
        if ($coursemodule->showdescription) {
            // Convert intro to html. Do not filter cached version, filters run at display time.
            $info->content = format_module_intro('edusharing', $edusharing, $coursemodule->id, false);
        }
        try {
            $resource = $DB->get_record('edusharing', ['id' => $coursemodule->instance], '*', MUST_EXIST);
            if (!empty($resource->popup_window)) {
                $info->onclick = 'this.target=\'_blank\';';
            }
        } catch (Exception $exception) {
            debugging($exception->getMessage());
        }
        return $info;
    }

    /**
     * Function get_inline_object_matches
     *
     * @param string $inputtext
     * @return array
     */
    public function get_inline_object_matches(string $inputtext): array {
        $contenttype = '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
        $dom = new DOMDocument();
        $dom->loadHTML($contenttype . $inputtext, LIBXML_NOERROR);
        $allelements = $dom->getElementsByTagName("*");
        $matches = [];
        foreach ($allelements as $item) {
            $classes = $item->attributes->getNamedItem('class')->nodeValue ?? '';
            if (str_contains($classes, 'edusharing_atto')) {
                $matches[] = $dom->saveHTML($item);
            }
        }
        return $matches;
    }

    /**
     * Function get_config_entry
     *
     * @param string $name
     * @return mixed
     * @throws dml_exception
     */
    public function get_config_entry(string $name): mixed {
        return $this->appconfig->get($name);
    }

    /**
     * Function set_config_entry
     *
     * @param string $name
     * @param mixed $value
     * @return void
     */
    public function set_config_entry(string $name, mixed $value): void {
        $this->appconfig->set($name, $value);
    }

    /**
     * Function get_internal_url
     *
     * Retrieves the internal URL from config.
     *
     * @return string
     */
    public function get_internal_url(): string {
        try {
            $internalurl = $this->appconfig->get('application_docker_network_url');
            if (empty($internalurl)) {
                $internalurl = $this->appconfig->get('application_cc_gui_url');
            }
            return rtrim($internalurl, '/');
        } catch (Exception $exception) {
            debugging($exception->getMessage());
            unset($exception);
        }
        return '';
    }
}