This commit is contained in:
Markos Gogoulos
2026-05-04 19:06:38 +03:00
parent 4238559b95
commit a89bbd141d
33 changed files with 514 additions and 353 deletions
@@ -39,9 +39,18 @@ class text_filter extends \core_filters\text_filter {
$pattern_tag = '/\[mediacms:([a-zA-Z0-9]+)\]/';
$newtext = preg_replace_callback($pattern_tag, [$this, 'callback_tag'], $newtext);
// 2. Auto-convert MediaCMS URLs to embedded players
// 2a. Convert MediaCMS URLs that are already inside <iframe src="..."> attributes
// (saved by the TinyMCE plugin) to launch.php URLs, preserving all other iframe
// attributes. This must run before 2b so the URL pattern below does not try to
// replace just the URL string and produce broken HTML inside the src attribute.
$iframe_src_pattern = '/(<iframe\b[^>]*?\s)src=(["\'])('
. $scheme . ':\/\/' . $host . $path_prefix
. '\/(view|embed)\?m=([a-zA-Z0-9]+)[^"\']*)\2/is';
$newtext = preg_replace_callback($iframe_src_pattern, [$this, 'callback_iframe_src'], $newtext);
// 2b. Auto-convert plain-text MediaCMS URLs to embedded players.
// First, protect text-only links from being converted
// by temporarily replacing them with placeholders
// by temporarily replacing them with placeholders.
$textlink_placeholders = [];
$textlink_pattern = '/<a\s+[^>]*data-mediacms-textlink=["\']true["\'][^>]*>.*?<\/a>/is';
@@ -51,8 +60,8 @@ class text_filter extends \core_filters\text_filter {
return $placeholder;
}, $newtext);
// Regex for MediaCMS view URLs: https://domain/view?m=TOKEN
// We need to be careful to match the configured domain
// Regex for plain-text MediaCMS view/embed URLs (not inside iframe src="" — those
// were already handled by 2a above).
$parsed_url = parse_url($mediacmsurl);
$host = preg_quote($parsed_url['host'] ?? '', '/');
$scheme = preg_quote($parsed_url['scheme'] ?? 'https', '/');
@@ -74,6 +83,50 @@ class text_filter extends \core_filters\text_filter {
return $newtext;
}
/**
* Callback for MediaCMS URLs found inside existing <iframe src="..."> attributes.
* Replaces only the src value with a launch.php URL so the rest of the iframe
* attributes (width, height, style, etc.) are preserved unchanged.
*
* $matches[1] — everything in the opening tag before `src=`
* $matches[2] — the quote character (" or ')
* $matches[3] — the full MediaCMS URL
* $matches[4] — "view" or "embed"
* $matches[5] — the media friendly_token
*/
public function callback_iframe_src($matches) {
global $COURSE;
$full_url = $matches[3];
$token = $matches[5];
$before_src = $matches[1]; // e.g. '<iframe style="..." '
$quote = $matches[2];
// Extract embed params from the original URL.
$embed_params = [];
$parsed_qs = parse_url($full_url);
if (isset($parsed_qs['query'])) {
// The saved URL may have HTML-entity-encoded ampersands.
$raw_query = html_entity_decode($parsed_qs['query'], ENT_QUOTES | ENT_HTML5);
parse_str($raw_query, $query_params);
foreach (['showTitle', 'showUserAvatar', 'linkTitle', 't', 'width', 'height'] as $p) {
if (isset($query_params[$p])) {
$embed_params[$p] = $query_params[$p];
}
}
}
$launch_params = array_merge(
['token' => $token, 'courseid' => $COURSE->id ?? 0],
$embed_params
);
$launch_url = (new moodle_url('/filter/mediacms/launch.php', $launch_params))->out(false);
// Reconstruct the opening iframe tag with the new src, keeping all other attributes.
return $before_src . 'src=' . $quote . $launch_url . $quote;
}
/**
* Callback for [mediacms:TOKEN]
*/
@@ -74,6 +74,14 @@ if ($show_media_page === 'true') {
}
$custom_params[] = "embed_share_media=" . $share_embedded_media;
// Pass the My Media base URL so MediaCMS can navigate the parent frame back into Moodle
// when the user clicks a media title inside the embed player (see parent_media_base in embeddedApp.ts).
$my_media_base = (new moodle_url('/filter/mediacms/my_media.php'))->out(false);
if ($courseid) {
$my_media_base .= '?courseid=' . intval($courseid);
}
$custom_params[] = "parent_media_base=" . $my_media_base;
// Set up page
$page_params = [
'token' => $mediatoken,