Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 25 additions & 10 deletions service/media_manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -197,24 +197,39 @@ protected function rewrite_iframe_node(\DOMElement $iframe)
$iframe->removeAttribute('onload');
}

foreach ($iframe->childNodes as $child_node)
$this->rewrite_xsl_iframe_attributes($iframe);

$iframe->setAttribute('data-consent-media-frame', '1');
}

/**
* Rewrite deferred attributes nested inside XSL control-flow elements.
*
* @param \DOMElement $parent Iframe or XSL control-flow element
*
* @return void
*/
protected function rewrite_xsl_iframe_attributes(\DOMElement $parent)
{
foreach ($parent->childNodes as $child_node)
{
if (!$child_node instanceof \DOMElement
|| $child_node->namespaceURI !== self::XSL_NAMESPACE
|| $child_node->localName !== 'attribute'
)
if (!$child_node instanceof \DOMElement || $child_node->namespaceURI !== self::XSL_NAMESPACE)
{
continue;
}

$name = $child_node->getAttribute('name');
if ($name === 'src' || $name === 'onload')
if ($child_node->localName === 'attribute')
{
$child_node->setAttribute('name', 'data-consent-' . $name);
$name = $child_node->getAttribute('name');
if ($name === 'src' || $name === 'onload')
{
$child_node->setAttribute('name', 'data-consent-' . $name);
}
continue;
}
}

$iframe->setAttribute('data-consent-media-frame', '1');
$this->rewrite_xsl_iframe_attributes($child_node);
}
}

/**
Expand Down
24 changes: 24 additions & 0 deletions tests/service/media_manager_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,30 @@ public function test_rewrite_iframe_node_rewrites_static_and_xsl_src_and_onload_
self::assertStringNotContainsString(' onload="boot()"', $template);
}

public function test_rewrite_iframe_node_rewrites_attributes_nested_in_xsl_control_flow()
{
$dom = \s9e\TextFormatter\Configurator\Helpers\TemplateLoader::load(
'<iframe>'
. '<xsl:choose xmlns:xsl="http://www.w3.org/1999/XSL/Transform">'
. '<xsl:when test="@episode_id">'
. '<xsl:attribute name="src">https://embed.example.com/episode/<xsl:value-of select="@episode_id"/></xsl:attribute>'
. '</xsl:when>'
. '<xsl:otherwise>'
. '<xsl:attribute name="src">https://embed.example.com/show/<xsl:value-of select="@podcast_id"/></xsl:attribute>'
. '</xsl:otherwise>'
. '</xsl:choose>'
. '</iframe>'
);
$iframe = $dom->getElementsByTagName('iframe')->item(0);

$this->invoke_method($this->manager, 'rewrite_iframe_node', [$iframe]);

$template = \s9e\TextFormatter\Configurator\Helpers\TemplateLoader::save($dom);
self::assertSame(2, substr_count($template, 'name="data-consent-src"'));
self::assertStringNotContainsString('name="src"', $template);
self::assertStringContainsString('data-consent-media-frame="1"', $template);
}

protected function invoke_method($object, $method_name, array $arguments = [])
{
$method = new \ReflectionMethod($object, $method_name);
Expand Down