| 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 | declare(strict_types=1);
 | 
        
           |  |  | 18 |   | 
        
           |  |  | 19 | namespace mod_edusharing;
 | 
        
           |  |  | 20 |   | 
        
           |  |  | 21 | use cached_cm_info;
 | 
        
           |  |  | 22 | use coding_exception;
 | 
        
           |  |  | 23 | use context_course;
 | 
        
           |  |  | 24 | use context_system;
 | 
        
           |  |  | 25 | use dml_exception;
 | 
        
           |  |  | 26 | use DOMDocument;
 | 
        
           |  |  | 27 | use Exception;
 | 
        
           |  |  | 28 | use stdClass;
 | 
        
           |  |  | 29 |   | 
        
           |  |  | 30 | /**
 | 
        
           |  |  | 31 |  * Class UtilityFunctions
 | 
        
           |  |  | 32 |  *
 | 
        
           |  |  | 33 |  * @author Marian Ziegler <ziegler@edu-sharing.net>
 | 
        
           |  |  | 34 |  * @package mod_edusharing
 | 
        
           |  |  | 35 |  */
 | 
        
           |  |  | 36 | class UtilityFunctions {
 | 
        
           |  |  | 37 |     /**
 | 
        
           |  |  | 38 |      * @var AppConfig|null
 | 
        
           |  |  | 39 |      */
 | 
        
           |  |  | 40 |     private ?AppConfig $appconfig;
 | 
        
           |  |  | 41 |   | 
        
           |  |  | 42 |     /**
 | 
        
           |  |  | 43 |      * UtilityFunctions constructor
 | 
        
           |  |  | 44 |      *
 | 
        
           |  |  | 45 |      * @param AppConfig|null $config
 | 
        
           |  |  | 46 |      */
 | 
        
           |  |  | 47 |     public function __construct(?AppConfig $config = null) {
 | 
        
           |  |  | 48 |         $this->appconfig = $config;
 | 
        
           |  |  | 49 |         $this->init();
 | 
        
           |  |  | 50 |     }
 | 
        
           |  |  | 51 |   | 
        
           |  |  | 52 |     /**
 | 
        
           |  |  | 53 |      * Function init
 | 
        
           |  |  | 54 |      *
 | 
        
           |  |  | 55 |      * @return void
 | 
        
           |  |  | 56 |      */
 | 
        
           |  |  | 57 |     private function init(): void {
 | 
        
           |  |  | 58 |         if ($this->appconfig === null) {
 | 
        
           |  |  | 59 |             $this->appconfig = new DefaultAppConfig();
 | 
        
           |  |  | 60 |         }
 | 
        
           |  |  | 61 |     }
 | 
        
           |  |  | 62 |   | 
        
           |  |  | 63 |     /**
 | 
        
           |  |  | 64 |      * Function get_object_id_from_url
 | 
        
           |  |  | 65 |      *
 | 
        
           |  |  | 66 |      * Get the object-id from object-url.
 | 
        
           |  |  | 67 |      * E.g. "abc-123-xyz-456789" for "ccrep://homeRepository/abc-123-xyz-456789"
 | 
        
           |  |  | 68 |      *
 | 
        
           |  |  | 69 |      * @param string $url
 | 
        
           |  |  | 70 |      * @return string
 | 
        
           |  |  | 71 |      */
 | 
        
           |  |  | 72 |     public function get_object_id_from_url(string $url): string {
 | 
        
           |  |  | 73 |         $objectid = parse_url($url, PHP_URL_PATH);
 | 
        
           |  |  | 74 |         if ($objectid === false) {
 | 
        
           |  |  | 75 |             try {
 | 
        
           |  |  | 76 |                 trigger_error(get_string('error_get_object_id_from_url', 'edusharing'), E_USER_WARNING);
 | 
        
           |  |  | 77 |             } catch (Exception $exception) {
 | 
        
           |  |  | 78 |                 unset($exception);
 | 
        
           |  |  | 79 |                 trigger_error('error_get_object_id_from_url', E_USER_WARNING);
 | 
        
           |  |  | 80 |             }
 | 
        
           |  |  | 81 |             return '';
 | 
        
           |  |  | 82 |         }
 | 
        
           |  |  | 83 |   | 
        
           |  |  | 84 |         return str_replace('/', '', $objectid);
 | 
        
           |  |  | 85 |     }
 | 
        
           |  |  | 86 |   | 
        
           |  |  | 87 |     /**
 | 
        
           |  |  | 88 |      * Function get_repository_id_from_url
 | 
        
           |  |  | 89 |      *
 | 
        
           |  |  | 90 |      * Get the repository-id from object-url.
 | 
        
           |  |  | 91 |      * E.g. "homeRepository" for "ccrep://homeRepository/abc-123-xyz-456789"
 | 
        
           |  |  | 92 |      *
 | 
        
           |  |  | 93 |      * @param string $url
 | 
        
           |  |  | 94 |      * @return string
 | 
        
           |  |  | 95 |      * @throws Exception
 | 
        
           |  |  | 96 |      */
 | 
        
           |  |  | 97 |     public function get_repository_id_from_url(string $url): string {
 | 
        
           |  |  | 98 |         $repoid = parse_url($url, PHP_URL_HOST);
 | 
        
           |  |  | 99 |         if ($repoid === false) {
 | 
        
           |  |  | 100 |             throw new Exception(get_string('error_get_repository_id_from_url', 'edusharing'));
 | 
        
           |  |  | 101 |         }
 | 
        
           |  |  | 102 |   | 
        
           |  |  | 103 |         return $repoid;
 | 
        
           |  |  | 104 |     }
 | 
        
           |  |  | 105 |   | 
        
           |  |  | 106 |     /**
 | 
        
           |  |  | 107 |      * Functions get_redirect_url
 | 
        
           |  |  | 108 |      *
 | 
        
           |  |  | 109 |      * @param stdClass $edusharing
 | 
        
           |  |  | 110 |      * @param string $displaymode
 | 
        
           |  |  | 111 |      * @return string
 | 
        
           |  |  | 112 |      * @throws coding_exception
 | 
        
           |  |  | 113 |      * @throws dml_exception
 | 
        
           |  |  | 114 |      */
 | 
        
           |  |  | 115 |     public function get_redirect_url(
 | 
        
           |  |  | 116 |         stdClass $edusharing,
 | 
        
           |  |  | 117 |         string $displaymode = Constants::EDUSHARING_DISPLAY_MODE_DISPLAY
 | 
        
           |  |  | 118 |     ): string {
 | 
        
           |  |  | 119 |         global $USER;
 | 
        
           |  |  | 120 |         $url = rtrim($this->get_config_entry('application_cc_gui_url'), '/');
 | 
        
           |  |  | 121 |         $url .= '/renderingproxy';
 | 
        
           |  |  | 122 |         $url .= '?app_id=' . urlencode($this->get_config_entry('application_appid'));
 | 
        
           |  |  | 123 |         $url .= '&session=' . urlencode(session_id());
 | 
        
           |  |  | 124 |         try {
 | 
        
           |  |  | 125 |             $repoid = $this->get_repository_id_from_url($edusharing->object_url);
 | 
        
           |  |  | 126 |         } catch (Exception $exception) {
 | 
        
           |  |  | 127 |             debugging($exception->getMessage());
 | 
        
           |  |  | 128 |             return '';
 | 
        
           |  |  | 129 |         }
 | 
        
           |  |  | 130 |         $url     .= '&rep_id=' . urlencode($repoid);
 | 
        
           |  |  | 131 |         $url     .= '&obj_id=' . urlencode($this->get_object_id_from_url($edusharing->object_url));
 | 
        
           |  |  | 132 |         $url     .= '&resource_id=' . urlencode($edusharing->id);
 | 
        
           |  |  | 133 |         $url     .= '&course_id=' . urlencode($edusharing->course);
 | 
        
           |  |  | 134 |         $context = context_course::instance($edusharing->course);
 | 
        
           |  |  | 135 |         $roles   = get_user_roles($context, $USER->id);
 | 
        
           |  |  | 136 |         foreach ($roles as $role) {
 | 
        
           |  |  | 137 |             $url .= '&role=' . urlencode($role->shortname);
 | 
        
           |  |  | 138 |         }
 | 
        
           |  |  | 139 |         $url .= '&display=' . urlencode($displaymode);
 | 
        
           |  |  | 140 |         $url .= '&version=' . urlencode($edusharing->object_version);
 | 
        
           |  |  | 141 |         $url .= '&locale=' . urlencode(current_language());
 | 
        
           |  |  | 142 |         $url .= '&language=' . urlencode(current_language());
 | 
        
           |  |  | 143 |         $url .= '&u=' . rawurlencode(base64_encode($this->encrypt_with_repo_key($this->get_auth_key())));
 | 
        
           |  |  | 144 |   | 
        
           |  |  | 145 |         return $url;
 | 
        
           |  |  | 146 |     }
 | 
        
           |  |  | 147 |   | 
        
           |  |  | 148 |     /**
 | 
        
           |  |  | 149 |      * Function get_auth_key
 | 
        
           |  |  | 150 |      *
 | 
        
           |  |  | 151 |      * @throws dml_exception
 | 
        
           |  |  | 152 |      */
 | 
        
           |  |  | 153 |     public function get_auth_key(): string {
 | 
        
           |  |  | 154 |         global $USER, $SESSION;
 | 
        
           |  |  | 155 |   | 
        
           |  |  | 156 |         // Set by external sso script.
 | 
        
           |  |  | 157 |         if (!empty($SESSION->edusharing_sso) && $this->get_config_entry('obfuscate_auth_param') === '1') {
 | 
        
           |  |  | 158 |             return $SESSION->edusharing_sso[$this->get_config_entry('EDU_AUTH_PARAM_NAME_USERID')];
 | 
        
           |  |  | 159 |         }
 | 
        
           |  |  | 160 |         $guestoption = $this->get_config_entry('edu_guest_option');
 | 
        
           |  |  | 161 |         if (!empty($guestoption)) {
 | 
        
           |  |  | 162 |             $guestid = $this->get_config_entry('edu_guest_guest_id');
 | 
        
           |  |  | 163 |   | 
        
           |  |  | 164 |             return !empty($guestid) ? $guestid : 'esguest';
 | 
        
           |  |  | 165 |         }
 | 
        
           |  |  | 166 |         $eduauthkey = $this->get_config_entry('EDU_AUTH_KEY');
 | 
        
           |  |  | 167 |         if ($eduauthkey == 'id') {
 | 
        
           |  |  | 168 |             return $USER->id;
 | 
        
           |  |  | 169 |         }
 | 
        
           |  |  | 170 |         if ($eduauthkey == 'idnumber') {
 | 
        
           |  |  | 171 |             return $USER->idnumber;
 | 
        
           |  |  | 172 |         }
 | 
        
           |  |  | 173 |         if ($eduauthkey == 'email') {
 | 
        
           |  |  | 174 |             return $USER->email;
 | 
        
           |  |  | 175 |         }
 | 
        
           |  |  | 176 |         if (isset($USER->profile[$eduauthkey])) {
 | 
        
           |  |  | 177 |             return $USER->profile[$eduauthkey];
 | 
        
           |  |  | 178 |         }
 | 
        
           |  |  | 179 |         return $USER->username . $this->get_config_entry('auth_suffix');
 | 
        
           |  |  | 180 |     }
 | 
        
           |  |  | 181 |   | 
        
           |  |  | 182 |     /**
 | 
        
           |  |  | 183 |      * Function encrypt_with_repo_key
 | 
        
           |  |  | 184 |      *
 | 
        
           |  |  | 185 |      * @param string $data
 | 
        
           |  |  | 186 |      * @return string
 | 
        
           |  |  | 187 |      * @throws coding_exception
 | 
        
           |  |  | 188 |      * @throws dml_exception
 | 
        
           |  |  | 189 |      */
 | 
        
           |  |  | 190 |     public function encrypt_with_repo_key(string $data): string {
 | 
        
           |  |  | 191 |         $encrypted = '';
 | 
        
           |  |  | 192 |         $key       = openssl_get_publickey($this->get_config_entry('repository_public_key'));
 | 
        
           |  |  | 193 |         if (!openssl_public_encrypt($data, $encrypted, $key)) {
 | 
        
           |  |  | 194 |             trigger_error(get_string('error_encrypt_with_repo_public', 'edusharing'), E_USER_WARNING);
 | 
        
           |  |  | 195 |             return '';
 | 
        
           |  |  | 196 |         }
 | 
        
           |  |  | 197 |         return $encrypted;
 | 
        
           |  |  | 198 |     }
 | 
        
           |  |  | 199 |   | 
        
           |  |  | 200 |     /**
 | 
        
           |  |  | 201 |      * Function set_moodle_ids_in_edusharing_entries
 | 
        
           |  |  | 202 |      *
 | 
        
           |  |  | 203 |      * @param string $text
 | 
        
           |  |  | 204 |      * @param int $sectionid
 | 
        
           |  |  | 205 |      * @param int $moduleid
 | 
        
           |  |  | 206 |      *
 | 
        
           |  |  | 207 |      * @throws dml_exception
 | 
        
           |  |  | 208 |      */
 | 
        
           |  |  | 209 |     public function set_moodle_ids_in_edusharing_entries(string $text, int $sectionid, int $moduleid = 0): void {
 | 
        
           |  |  | 210 |         global $DB;
 | 
        
           |  |  | 211 |         $esmatches = $this->get_inline_object_matches($text);
 | 
        
           |  |  | 212 |         foreach ($esmatches as $match) {
 | 
        
           |  |  | 213 |             $resourceid = $this->get_resource_id_from_match($match);
 | 
        
           |  |  | 214 |             $edusharing = $DB->get_record('edusharing', ['id' => $resourceid], '*', MUST_EXIST);
 | 
        
           |  |  | 215 |             $edusharing->section_id = $sectionid;
 | 
        
           |  |  | 216 |             if ($moduleid !== 0) {
 | 
        
           |  |  | 217 |                 $edusharing->module_id = $moduleid;
 | 
        
           |  |  | 218 |             }
 | 
        
           |  |  | 219 |             $DB->update_record('edusharing', $edusharing);
 | 
        
           |  |  | 220 |         }
 | 
        
           |  |  | 221 |     }
 | 
        
           |  |  | 222 |   | 
        
           |  |  | 223 |     /**
 | 
        
           |  |  | 224 |      * Function get_resource_id_from_match
 | 
        
           |  |  | 225 |      *
 | 
        
           |  |  | 226 |      * @param string $match
 | 
        
           |  |  | 227 |      * @return string
 | 
        
           |  |  | 228 |      */
 | 
        
           |  |  | 229 |     public function get_resource_id_from_match(string $match): string {
 | 
        
           |  |  | 230 |         $resourceid = '';
 | 
        
           |  |  | 231 |         $pos        = strpos($match, 'resourceid="');
 | 
        
           |  |  | 232 |         $offset     = 12;
 | 
        
           |  |  | 233 |         if ($pos === false) {
 | 
        
           |  |  | 234 |             $pos = strpos($match, "resourceId=");
 | 
        
           |  |  | 235 |             $offset = 11;
 | 
        
           |  |  | 236 |         }
 | 
        
           |  |  | 237 |         if ($pos !== false) {
 | 
        
           |  |  | 238 |             $resourceid = substr($match, $pos + $offset);
 | 
        
           |  |  | 239 |             $resourceid = substr($resourceid, 0, strpos($resourceid, "&"));
 | 
        
           |  |  | 240 |         }
 | 
        
           |  |  | 241 |         return $resourceid;
 | 
        
           |  |  | 242 |     }
 | 
        
           |  |  | 243 |   | 
        
           |  |  | 244 |     /**
 | 
        
           |  |  | 245 |      * Function update_settings_images
 | 
        
           |  |  | 246 |      *
 | 
        
           |  |  | 247 |      * @param string $settingname
 | 
        
           |  |  | 248 |      * @return void
 | 
        
           |  |  | 249 |      */
 | 
        
           |  |  | 250 |     public function update_settings_images(string $settingname): void {
 | 
        
           |  |  | 251 |         global $CFG;
 | 
        
           |  |  | 252 |         // The setting name that was updated comes as a string like 's_theme_photo_loginbackgroundimage'.
 | 
        
           |  |  | 253 |         // We split it on '_' characters.
 | 
        
           |  |  | 254 |         $parts = explode('_', $settingname);
 | 
        
           |  |  | 255 |         // And get the last one to get the setting name..
 | 
        
           |  |  | 256 |         $settingname = end($parts);
 | 
        
           |  |  | 257 |         // Admin settings are stored in system context.
 | 
        
           |  |  | 258 |         try {
 | 
        
           |  |  | 259 |             $syscontext = context_system::instance();
 | 
        
           |  |  | 260 |             $filename   = $this->get_config_entry($settingname);
 | 
        
           |  |  | 261 |         } catch (Exception $exception) {
 | 
        
           |  |  | 262 |             debugging($exception->getMessage());
 | 
        
           |  |  | 263 |             return;
 | 
        
           |  |  | 264 |         }
 | 
        
           |  |  | 265 |         // This is the value of the admin setting which is the filename of the uploaded file.
 | 
        
           |  |  | 266 |         // We extract the file extension because we want to preserve it.
 | 
        
           |  |  | 267 |         $extension = substr($filename, strrpos($filename, '.') + 1);
 | 
        
           |  |  | 268 |         // This is the path in the moodle internal file system.
 | 
        
           |  |  | 269 |         $fullpath = "/{$syscontext->id}/" . 'edusharing' . "/{$settingname}/0{$filename}";
 | 
        
           |  |  | 270 |         // Get an instance of the moodle file storage.
 | 
        
           |  |  | 271 |         $fs = get_file_storage();
 | 
        
           |  |  | 272 |         // This is an efficient way to get a file if we know the exact path.
 | 
        
           |  |  | 273 |         if ($file = $fs->get_file_by_hash(sha1($fullpath))) {
 | 
        
           |  |  | 274 |             // We got the stored file - copy it to data root.
 | 
        
           |  |  | 275 |             // This location matches the searched for location in theme_config::resolve_image_location.
 | 
        
           |  |  | 276 |             $pathname = $CFG->dataroot . '/pix_plugins/mod/edusharing/icon.' . $extension;
 | 
        
           |  |  | 277 |             // This pattern matches any previous files with maybe different file extensions.
 | 
        
           |  |  | 278 |             $pathpattern = $CFG->dataroot . '/pix_plugins/mod/edusharing/icon.*';
 | 
        
           |  |  | 279 |             // Make sure this dir exists.
 | 
        
           |  |  | 280 |             @mkdir($CFG->dataroot . '/pix_plugins/mod/edusharing/', $CFG->directorypermissions, true);
 | 
        
           |  |  | 281 |             // Delete any existing files for this setting.
 | 
        
           |  |  | 282 |             foreach (glob($pathpattern) as $filename) {
 | 
        
           |  |  | 283 |                 @unlink($filename);
 | 
        
           |  |  | 284 |             }
 | 
        
           |  |  | 285 |             // Copy the current file to this location.
 | 
        
           |  |  | 286 |             $file->copy_content_to($pathname);
 | 
        
           |  |  | 287 |         } else {
 | 
        
           |  |  | 288 |             $pathpattern = $CFG->dataroot . '/pix_plugins/mod/edusharing/icon.*';
 | 
        
           |  |  | 289 |             // Make sure this dir exists.
 | 
        
           |  |  | 290 |             @mkdir($CFG->dataroot . '/pix_plugins/mod/edusharing/', $CFG->directorypermissions, true);
 | 
        
           |  |  | 291 |             // Delete any existing files for this setting.
 | 
        
           |  |  | 292 |             foreach (glob($pathpattern) as $filename) {
 | 
        
           |  |  | 293 |                 @unlink($filename);
 | 
        
           |  |  | 294 |             }
 | 
        
           |  |  | 295 |         }
 | 
        
           |  |  | 296 |         // Reset theme caches.
 | 
        
           |  |  | 297 |         theme_reset_all_caches();
 | 
        
           |  |  | 298 |     }
 | 
        
           |  |  | 299 |   | 
        
           |  |  | 300 |     /**
 | 
        
           |  |  | 301 |      * Function get_course_module_info
 | 
        
           |  |  | 302 |      *
 | 
        
           |  |  | 303 |      * @param stdClass $coursemodule
 | 
        
           |  |  | 304 |      * @return cached_cm_info|bool
 | 
        
           |  |  | 305 |      */
 | 
        
           |  |  | 306 |     public function get_course_module_info(stdClass $coursemodule): cached_cm_info|bool {
 | 
        
           |  |  | 307 |         global $DB;
 | 
        
           |  |  | 308 |         try {
 | 
        
           |  |  | 309 |             $edusharing = $DB->get_record(
 | 
        
           |  |  | 310 |                 'edusharing',
 | 
        
           |  |  | 311 |                 ['id' => $coursemodule->instance],
 | 
        
           |  |  | 312 |                 'id, name, intro, introformat',
 | 
        
           |  |  | 313 |                 MUST_EXIST
 | 
        
           |  |  | 314 |             );
 | 
        
           |  |  | 315 |         } catch (Exception $exception) {
 | 
        
           |  |  | 316 |             debugging($exception->getMessage());
 | 
        
           |  |  | 317 |             return false;
 | 
        
           |  |  | 318 |         }
 | 
        
           |  |  | 319 |         $info = new cached_cm_info();
 | 
        
           |  |  | 320 |         if ($coursemodule->showdescription) {
 | 
        
           |  |  | 321 |             // Convert intro to html. Do not filter cached version, filters run at display time.
 | 
        
           |  |  | 322 |             $info->content = format_module_intro('edusharing', $edusharing, $coursemodule->id, false);
 | 
        
           |  |  | 323 |         }
 | 
        
           |  |  | 324 |         try {
 | 
        
           |  |  | 325 |             $resource = $DB->get_record('edusharing', ['id' => $coursemodule->instance], '*', MUST_EXIST);
 | 
        
           |  |  | 326 |             if (!empty($resource->popup_window)) {
 | 
        
           |  |  | 327 |                 $info->onclick = 'this.target=\'_blank\';';
 | 
        
           |  |  | 328 |             }
 | 
        
           |  |  | 329 |         } catch (Exception $exception) {
 | 
        
           |  |  | 330 |             debugging($exception->getMessage());
 | 
        
           |  |  | 331 |         }
 | 
        
           |  |  | 332 |         return $info;
 | 
        
           |  |  | 333 |     }
 | 
        
           |  |  | 334 |   | 
        
           |  |  | 335 |     /**
 | 
        
           |  |  | 336 |      * Function get_inline_object_matches
 | 
        
           |  |  | 337 |      *
 | 
        
           |  |  | 338 |      * @param string $inputtext
 | 
        
           |  |  | 339 |      * @return array
 | 
        
           |  |  | 340 |      */
 | 
        
           |  |  | 341 |     public function get_inline_object_matches(string $inputtext): array {
 | 
        
           |  |  | 342 |         $contenttype = '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
 | 
        
           |  |  | 343 |         $dom = new DOMDocument();
 | 
        
           |  |  | 344 |         $dom->loadHTML($contenttype . $inputtext, LIBXML_NOERROR);
 | 
        
           |  |  | 345 |         $allelements = $dom->getElementsByTagName("*");
 | 
        
           |  |  | 346 |         $matches = [];
 | 
        
           |  |  | 347 |         foreach ($allelements as $item) {
 | 
        
           |  |  | 348 |             $classes = $item->attributes->getNamedItem('class')->nodeValue ?? '';
 | 
        
           |  |  | 349 |             if (str_contains($classes, 'edusharing_atto')) {
 | 
        
           |  |  | 350 |                 $matches[] = $dom->saveHTML($item);
 | 
        
           |  |  | 351 |             }
 | 
        
           |  |  | 352 |         }
 | 
        
           |  |  | 353 |         return $matches;
 | 
        
           |  |  | 354 |     }
 | 
        
           |  |  | 355 |   | 
        
           |  |  | 356 |     /**
 | 
        
           |  |  | 357 |      * Function get_config_entry
 | 
        
           |  |  | 358 |      *
 | 
        
           |  |  | 359 |      * @param string $name
 | 
        
           |  |  | 360 |      * @return mixed
 | 
        
           |  |  | 361 |      * @throws dml_exception
 | 
        
           |  |  | 362 |      */
 | 
        
           |  |  | 363 |     public function get_config_entry(string $name): mixed {
 | 
        
           |  |  | 364 |         return $this->appconfig->get($name);
 | 
        
           |  |  | 365 |     }
 | 
        
           |  |  | 366 |   | 
        
           |  |  | 367 |     /**
 | 
        
           |  |  | 368 |      * Function set_config_entry
 | 
        
           |  |  | 369 |      *
 | 
        
           |  |  | 370 |      * @param string $name
 | 
        
           |  |  | 371 |      * @param mixed $value
 | 
        
           |  |  | 372 |      * @return void
 | 
        
           |  |  | 373 |      */
 | 
        
           |  |  | 374 |     public function set_config_entry(string $name, mixed $value): void {
 | 
        
           |  |  | 375 |         $this->appconfig->set($name, $value);
 | 
        
           |  |  | 376 |     }
 | 
        
           |  |  | 377 |   | 
        
           |  |  | 378 |     /**
 | 
        
           |  |  | 379 |      * Function get_internal_url
 | 
        
           |  |  | 380 |      *
 | 
        
           |  |  | 381 |      * Retrieves the internal URL from config.
 | 
        
           |  |  | 382 |      *
 | 
        
           |  |  | 383 |      * @return string
 | 
        
           |  |  | 384 |      */
 | 
        
           |  |  | 385 |     public function get_internal_url(): string {
 | 
        
           |  |  | 386 |         try {
 | 
        
           |  |  | 387 |             $internalurl = $this->appconfig->get('application_docker_network_url');
 | 
        
           |  |  | 388 |             if (empty($internalurl)) {
 | 
        
           |  |  | 389 |                 $internalurl = $this->appconfig->get('application_cc_gui_url');
 | 
        
           |  |  | 390 |             }
 | 
        
           |  |  | 391 |             return rtrim($internalurl, '/');
 | 
        
           |  |  | 392 |         } catch (Exception $exception) {
 | 
        
           |  |  | 393 |             debugging($exception->getMessage());
 | 
        
           |  |  | 394 |             unset($exception);
 | 
        
           |  |  | 395 |         }
 | 
        
           |  |  | 396 |         return '';
 | 
        
           |  |  | 397 |     }
 | 
        
           |  |  | 398 | }
 |