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/>./*** Represents a Zoom invitation.** @package mod_zoom* @author Andrew Madden <andrewmadden@catalyst-au.net>* @copyright 2021 Catalyst IT* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/namespace mod_zoom;use coding_exception;use context_module;use moodle_exception;/*** Invitation class.*/class invitation {/*** Invitation settings prefix.* @var string*/public const PREFIX = 'invitation_';/** @var string|null $invitation The unaltered zoom invitation text. */private $invitation;/** @var array $configregex Array of regex patterns defined in plugin settings. */private $configregex;/*** invitation constructor.** @param string|null $invitation Zoom invitation returned from* https://marketplace.zoom.us/docs/api-reference/zoom-api/meetings/meetinginvitation.*/public function __construct($invitation) {$this->invitation = $invitation;}/*** Get the display string to show on the module page.** @param int $coursemoduleid Course module where the user will view the invitation.* @param int|null $userid Optionally supply the intended user to view the string. Defaults to global $USER.* @return ?string*/public function get_display_string(int $coursemoduleid, ?int $userid = null) {if (empty($this->invitation)) {return null;}// If regex patterns are disabled, return the raw zoom meeting invitation.if (!get_config('zoom', 'invitationregexenabled')) {return $this->invitation;}$displaystring = $this->invitation;try {// If setting enabled, strip the invite message.if (get_config('zoom', 'invitationremoveinvite')) {$displaystring = $this->remove_element($displaystring, 'invite');}// If setting enabled, strip the iCal link.if (get_config('zoom', 'invitationremoveicallink')) {$displaystring = $this->remove_element($displaystring, 'icallink');}// Check user capabilities, and remove parts of the invitation they don't have permission to view.if (!has_capability('mod/zoom:viewjoinurl', context_module::instance($coursemoduleid), $userid)) {$displaystring = $this->remove_element($displaystring, 'joinurl');}if (!has_capability('mod/zoom:viewdialin', context_module::instance($coursemoduleid), $userid)) {$displaystring = $this->remove_element($displaystring, 'onetapmobile');$displaystring = $this->remove_element($displaystring, 'dialin');$displaystring = $this->remove_element($displaystring, 'sip');$displaystring = $this->remove_element($displaystring, 'h323');} else {// Fix the formatting of the onetapmobile section if it exists.$displaystring = $this->add_paragraph_break_above_element($displaystring, 'onetapmobile');}} catch (moodle_exception $e) {// If the regex parsing fails, log a debugging message and return the whole invitation.debugging($e->getMessage(), DEBUG_DEVELOPER);return $this->invitation;}$displaystring = trim($this->clean_paragraphs($displaystring));return $displaystring;}/*** Remove instances of a zoom invitation element using a regex pattern.** @param string $invitation* @param string $element* @return string** @throws \coding_exception* @throws \dml_exception* @throws \moodle_exception*/private function remove_element(string $invitation, string $element): string {global $PAGE;$configregex = $this->get_config_invitation_regex();if (!array_key_exists($element, $configregex)) {throw new coding_exception('Cannot remove element: ' . $element. '. See mod/zoom/classes/invitation.php:get_default_invitation_regex for valid elements.');}// If the element pattern is intentionally empty, return the invitation string unaltered.if (empty($configregex[$element])) {return $invitation;}$count = 0;$invitation = @preg_replace($configregex[$element], "", $invitation, -1, $count);// If invitation is null, an error occurred in preg_replace.if ($invitation === null) {throw new moodle_exception('invitationmodificationfailed','mod_zoom',$PAGE->url,['element' => $element, 'pattern' => $configregex[$element]]);}// Add debugging message to assist site administrator in testing regex patterns if no match is found.if (empty($count)) {debugging(get_string('invitationmatchnotfound','mod_zoom',['element' => $element, 'pattern' => $configregex[$element]]),DEBUG_DEVELOPER);}return $invitation;}/*** Add a paragraph break above an element defined by a regex pattern in a zoom invitation.** @param string $invitation* @param string $element* @return string** @throws \coding_exception* @throws \dml_exception*/private function add_paragraph_break_above_element(string $invitation, string $element): string {$matches = [];$configregex = $this->get_config_invitation_regex();// If no pattern found for element, return the invitation string unaltered.if (empty($configregex[$element])) {return $invitation;}$result = preg_match($configregex[$element], $invitation, $matches, PREG_OFFSET_CAPTURE);// If error occurred in preg_match, show debugging message to help site administrator.if ($result === false) {debugging(get_string('invitationmodificationfailed','mod_zoom',['element' => $element, 'pattern' => $configregex[$element]]),DEBUG_DEVELOPER);}// No match found, so return invitation string unaltered.if (empty($matches)) {return $invitation;}// Get the position of the element in the full invitation string.$pos = $matches[0][1];// Inject a paragraph break above element. Use $this->clean_paragraphs() to fix uneven breaks between paragraphs.return substr_replace($invitation, "\r\n\r\n", $pos, 0);}/*** Ensure that paragraphs in string have correct spacing.** @param string $invitation* @return string*/private function clean_paragraphs(string $invitation): string {// Replace partial paragraph breaks with exactly two line breaks.$invitation = preg_replace("/\r\n\n/m", "\r\n\r\n", $invitation);// Replace breaks of more than two line breaks with exactly two.$invitation = preg_replace("/\r\n\r\n[\r\n]+/m", "\r\n\r\n", $invitation);return $invitation;}/*** Get regex patterns from site config to find the different zoom invitation elements.** @return array* @throws \dml_exception*/private function get_config_invitation_regex(): array {if ($this->configregex !== null) {return $this->configregex;}$config = get_config('zoom');$this->configregex = [];// Get the regex defined in the plugin settings for each element.foreach (self::get_default_invitation_regex() as $element => $pattern) {$settingname = self::PREFIX . $element;$this->configregex[$element] = $config->$settingname;}return $this->configregex;}/*** Get default regex patterns to find the different zoom invitation elements.** @return string[]*/public static function get_default_invitation_regex(): array {return ['invite' => '/^.+is inviting you to a scheduled zoom meeting.+$/mi','joinurl' => '/^join zoom meeting.*(\n.*)+?(\nmeeting id.+\npasscode.+)$/mi','onetapmobile' => '/^one tap mobile.*(\n\s*\+.+)+$/mi','dialin' => '/^dial by your location.*(\n\s*\+.+)+(\n.*)+find your local number.+$/mi','sip' => '/^join by sip.*\n.+$/mi','h323' => '/^join by h\.323.*(\n.*)+?(\nmeeting id.+\npasscode.+)$/mi','icallink' => '/^.+download and import the following iCalendar.+$\n.+$/mi',];}}