Skip to content

Commit 7b12cac

Browse files
committed
Added SVG stripping from RSS feed item descriptions.
1 parent 0d227b7 commit 7b12cac

2 files changed

Lines changed: 130 additions & 0 deletions

File tree

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Drupal\do_feed\Hook;
6+
7+
use Drupal\Core\Hook\Attribute\Hook;
8+
9+
/**
10+
* Strips SVG elements from RSS feed item descriptions.
11+
*/
12+
final class PreprocessViewsViewRowRssHook {
13+
14+
/**
15+
* Implements hook_preprocess_views_view_row_rss().
16+
*/
17+
#[Hook('preprocess_views_view_row_rss')]
18+
public function preprocess(array &$variables): void {
19+
if (!isset($variables['description']) || !is_string($variables['description'])) {
20+
return;
21+
}
22+
23+
$variables['description'] = preg_replace('/<svg[^>]*>.*?<\/svg>/si', '', $variables['description']) ?? $variables['description'];
24+
}
25+
26+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Drupal\Tests\do_feed\Unit\Hook;
6+
7+
use Drupal\do_feed\Hook\PreprocessViewsViewRowRssHook;
8+
use Drupal\Tests\UnitTestCase;
9+
use PHPUnit\Framework\Attributes\CoversClass;
10+
use PHPUnit\Framework\Attributes\DataProvider;
11+
use PHPUnit\Framework\Attributes\Group;
12+
13+
/**
14+
* Tests for PreprocessViewsViewRowRssHook.
15+
*/
16+
#[CoversClass(PreprocessViewsViewRowRssHook::class)]
17+
#[Group('do_feed')]
18+
class PreprocessViewsViewRowRssHookTest extends UnitTestCase {
19+
20+
/**
21+
* Tests SVG stripping from RSS item descriptions.
22+
*/
23+
#[DataProvider('dataProviderSvgStripping')]
24+
public function testSvgStripping(string $input, string $expected): void {
25+
$hook = new PreprocessViewsViewRowRssHook();
26+
$variables = ['description' => $input];
27+
28+
$hook->preprocess($variables);
29+
30+
$this->assertEquals($expected, $variables['description']);
31+
}
32+
33+
/**
34+
* Data provider for `testSvgStripping()`.
35+
*
36+
* @return array<string, array{string, string}>
37+
* Test cases: input description, expected output.
38+
*/
39+
public static function dataProviderSvgStripping(): array {
40+
return [
41+
'no svg' => [
42+
'<p>Hello world</p>',
43+
'<p>Hello world</p>',
44+
],
45+
'simple svg' => [
46+
'<p>Text</p><svg><path d="M0 0"/></svg><p>More</p>',
47+
'<p>Text</p><p>More</p>',
48+
],
49+
'svg with attributes' => [
50+
'<p>Text</p><svg width="24" height="24" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/></svg><p>More</p>',
51+
'<p>Text</p><p>More</p>',
52+
],
53+
'multiple svgs' => [
54+
'<svg><path/></svg><p>Between</p><svg class="icon"><rect/></svg>',
55+
'<p>Between</p>',
56+
],
57+
'multiline svg' => [
58+
"<p>Text</p>\n<svg\n class=\"icon\"\n viewBox=\"0 0 24 24\">\n <path d=\"M0 0\"/>\n</svg>\n<p>More</p>",
59+
"<p>Text</p>\n\n<p>More</p>",
60+
],
61+
'svg with inner svg-like content' => [
62+
'<svg xmlns="http://www.w3.org/2000/svg"><path d="M0 0"/></svg><p>After</p>',
63+
'<p>After</p>',
64+
],
65+
'empty string' => ['', ''],
66+
];
67+
}
68+
69+
/**
70+
* Tests that non-string or missing descriptions are skipped.
71+
*/
72+
#[DataProvider('dataProviderSkipsNonString')]
73+
public function testSkipsNonString(array $variables, array $expected): void {
74+
$hook = new PreprocessViewsViewRowRssHook();
75+
76+
$hook->preprocess($variables);
77+
78+
$this->assertEquals($expected, $variables);
79+
}
80+
81+
/**
82+
* Data provider for `testSkipsNonString()`.
83+
*
84+
* @return array<string, array{array<string, mixed>, array<string, mixed>}>
85+
* Test cases: input variables, expected variables.
86+
*/
87+
public static function dataProviderSkipsNonString(): array {
88+
return [
89+
'no description key' => [
90+
['title' => 'Test'],
91+
['title' => 'Test'],
92+
],
93+
'null description' => [
94+
['description' => NULL],
95+
['description' => NULL],
96+
],
97+
'array description' => [
98+
['description' => ['#markup' => '<svg/>']],
99+
['description' => ['#markup' => '<svg/>']],
100+
],
101+
];
102+
}
103+
104+
}

0 commit comments

Comments
 (0)