From d0384c770548f926f384995338587f0cc6e05773 Mon Sep 17 00:00:00 2001 From: nlighteneddesign <nic@nlighteneddevelopment.com> Date: Thu, 23 Jan 2025 08:45:42 -0500 Subject: [PATCH 1/7] Add div and img --- core/lib/Drupal/Core/EventSubscriber/RssResponseCdata.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib/Drupal/Core/EventSubscriber/RssResponseCdata.php b/core/lib/Drupal/Core/EventSubscriber/RssResponseCdata.php index 4c3c88726d0b..57f93bd6eeb5 100644 --- a/core/lib/Drupal/Core/EventSubscriber/RssResponseCdata.php +++ b/core/lib/Drupal/Core/EventSubscriber/RssResponseCdata.php @@ -54,7 +54,7 @@ protected function wrapDescriptionCdata(string $rss_markup): string|false { foreach ($item->getElementsByTagName('description') as $node) { $html_markup = $node->nodeValue; if (!empty($html_markup)) { - $html_markup = Xss::filter($html_markup, ['a', 'abbr', 'acronym', 'address', 'b', 'bdo', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'col', 'colgroup', 'dd', 'del', 'dfn', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'ins', 'kbd', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var']); + $html_markup = Xss::filter($html_markup, ['a', 'abbr', 'acronym', 'address', 'b', 'bdo', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'col', 'colgroup', 'dd', 'del', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'ins', 'kbd', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var']); $new_node = $rss_dom->createCDATASection($html_markup); $node->replaceChild($new_node, $node->firstChild); } -- GitLab From 1ba34dd4beb994ca1ec823917cefe6c38e202c78 Mon Sep 17 00:00:00 2001 From: nicxvan <nic@nlightened.net> Date: Mon, 27 Jan 2025 00:20:29 -0500 Subject: [PATCH 2/7] Use text format --- core/core.services.yml | 1 + .../Core/EventSubscriber/RssResponseCdata.php | 19 ++++++-- .../system/config/schema/system.schema.yml | 3 ++ core/modules/system/src/Form/RssFeedsForm.php | 45 +++++++++++++++++++ 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/core/core.services.yml b/core/core.services.yml index 2dff154d821b..6be6109fb26a 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1832,6 +1832,7 @@ services: arguments: ['@current_user', '@path.current', '@path.matcher', '@language_manager'] response_filter.rss.cdata: class: Drupal\Core\EventSubscriber\RssResponseCdata + arguments: ['@config.factory', '@renderer'] response_filter.rss.relative_url: class: Drupal\Core\EventSubscriber\RssResponseRelativeUrlFilter messenger: diff --git a/core/lib/Drupal/Core/EventSubscriber/RssResponseCdata.php b/core/lib/Drupal/Core/EventSubscriber/RssResponseCdata.php index 57f93bd6eeb5..87dfa6d65d3d 100644 --- a/core/lib/Drupal/Core/EventSubscriber/RssResponseCdata.php +++ b/core/lib/Drupal/Core/EventSubscriber/RssResponseCdata.php @@ -2,7 +2,8 @@ namespace Drupal\Core\EventSubscriber; -use Drupal\Component\Utility\Xss; +use Drupal\Core\Config\ConfigFactoryInterface; +use Drupal\Core\Render\RendererInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; @@ -12,6 +13,11 @@ */ class RssResponseCdata implements EventSubscriberInterface { + public function __construct( + protected readonly ConfigFactoryInterface $configFactory, + protected readonly RendererInterface $renderer, + ) {} + /** * Wraps RSS descriptions in CDATA. * @@ -49,13 +55,20 @@ protected function wrapDescriptionCdata(string $rss_markup): string|false { if ($errors) { return $rss_markup; } + $config = $this->configFactory->get('system.rss'); + $format = $config->get('items.text_format') ?: 'basic_html'; foreach ($rss_dom->getElementsByTagName('item') as $item) { foreach ($item->getElementsByTagName('description') as $node) { $html_markup = $node->nodeValue; if (!empty($html_markup)) { - $html_markup = Xss::filter($html_markup, ['a', 'abbr', 'acronym', 'address', 'b', 'bdo', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'col', 'colgroup', 'dd', 'del', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'ins', 'kbd', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var']); - $new_node = $rss_dom->createCDATASection($html_markup); + $processed = [ + '#type' => 'processed_text', + '#text' => $html_markup, + '#format' => $format, + ]; + $markup = $this->renderer->renderInIsolation($processed); + $new_node = $rss_dom->createCDATASection($markup); $node->replaceChild($new_node, $node->firstChild); } } diff --git a/core/modules/system/config/schema/system.schema.yml b/core/modules/system/config/schema/system.schema.yml index 0c7cfac313c3..60c503ef038b 100644 --- a/core/modules/system/config/schema/system.schema.yml +++ b/core/modules/system/config/schema/system.schema.yml @@ -246,6 +246,9 @@ system.rss: type: mapping label: 'Feed items' mapping: + text_format: + type: string + label: 'Feed text format' view_mode: type: string label: 'Feed content' diff --git a/core/modules/system/src/Form/RssFeedsForm.php b/core/modules/system/src/Form/RssFeedsForm.php index 72617220f2c0..2be88f81bb59 100644 --- a/core/modules/system/src/Form/RssFeedsForm.php +++ b/core/modules/system/src/Form/RssFeedsForm.php @@ -4,6 +4,9 @@ use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Session\AccountProxyInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; + /** * Configure RSS settings for this site. @@ -12,6 +15,19 @@ */ class RssFeedsForm extends ConfigFormBase { + public function __construct( + protected readonly AccountProxyInterface $currentUser, + ) {} + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('current_user') + ); + } + /** * {@inheritdoc} */ @@ -30,6 +46,8 @@ protected function getEditableConfigNames() { * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { + $text_formats = $this->getTextFormats(); + $form['feed_view_mode'] = [ '#type' => 'select', '#title' => $this->t('Feed content'), @@ -42,7 +60,34 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#description' => $this->t('Global setting for the default display of content items in each feed.'), ]; + $form['text_format'] = [ + '#type' => 'select', + '#title' => $this->t('Text Format'), + '#config_target' => 'system.rss:items.text_format', + '#description' => $this->t('Choose a text format to apply to RSS feeds.'), + '#options' => $text_formats, + '#required' => TRUE, + '#default' => 'basic_html', + ]; + return parent::buildForm($form, $form_state); } + /** + * Helper function to get available text formats. + * + * @return array + * An array of text formats. + */ + protected function getTextFormats() { + $available_formats = []; + foreach (filter_formats() as $format) { + // Check if the current user has access to use this format. + if ($format->status() && $format->access('use', $this->currentUser)) { + $available_formats[$format->id()] = $format->label(); + } + } + return $available_formats; + } + } -- GitLab From cd444b0af89eda2de74057b0bff7063f2cef0421 Mon Sep 17 00:00:00 2001 From: nicxvan <nic@nlightened.net> Date: Mon, 27 Jan 2025 00:40:45 -0500 Subject: [PATCH 3/7] CS and STAN --- core/modules/system/src/Form/RssFeedsForm.php | 3 +-- .../Core/EventSubscriber/RssResponseCdataTest.php | 13 ++++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/core/modules/system/src/Form/RssFeedsForm.php b/core/modules/system/src/Form/RssFeedsForm.php index 2be88f81bb59..e507a2206e18 100644 --- a/core/modules/system/src/Form/RssFeedsForm.php +++ b/core/modules/system/src/Form/RssFeedsForm.php @@ -7,7 +7,6 @@ use Drupal\Core\Session\AccountProxyInterface; use Symfony\Component\DependencyInjection\ContainerInterface; - /** * Configure RSS settings for this site. * @@ -22,7 +21,7 @@ public function __construct( /** * {@inheritdoc} */ - public static function create(ContainerInterface $container) { + public static function create(ContainerInterface $container): static { return new static( $container->get('current_user') ); diff --git a/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php b/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php index ccacafc20645..5101ba00587d 100644 --- a/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php +++ b/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php @@ -4,7 +4,9 @@ namespace Drupal\Tests\Core\EventSubscriber; +use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\EventSubscriber\RssResponseCdata; +use Drupal\Core\Render\RendererInterface; use Drupal\Tests\UnitTestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -132,7 +134,16 @@ public function testOnResponse(string $content, string $expected_content): void ]) ); - $url_filter = new RssResponseCdata(); + $configMock = $this->createMock(Config::class); + $configMock->method('get')->willReturn('mocked_value'); + + $configFactoryMock = $this->createMock(ConfigFactoryInterface::class); + $configFactoryMock->method('get')->willReturn($configMock); + + // Mock the RendererInterface. + $rendererMock = $this->createMock(RendererInterface::class); + $rendererMock->method('render')->willReturn('<rendered output>'); + $url_filter = new RssResponseCdata($configFactoryMock, $rendererMock); $url_filter->onResponse($event); $this->assertEquals($expected_content, $event->getResponse()->getContent()); -- GitLab From 792fe9c56eba1dad4709078cfe8b35f225dfd446 Mon Sep 17 00:00:00 2001 From: andrew farquharson <2562-andrewfarq@users.noreply.drupalcode.org> Date: Mon, 27 Jan 2025 06:22:05 +0000 Subject: [PATCH 4/7] Edit RssResponseCdataTest.php Remove mock of Config class --- .../Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php b/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php index 5101ba00587d..582a357ae85c 100644 --- a/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php +++ b/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php @@ -134,9 +134,6 @@ public function testOnResponse(string $content, string $expected_content): void ]) ); - $configMock = $this->createMock(Config::class); - $configMock->method('get')->willReturn('mocked_value'); - $configFactoryMock = $this->createMock(ConfigFactoryInterface::class); $configFactoryMock->method('get')->willReturn($configMock); -- GitLab From 130ae16856a940a9afaee8a5df97f2c2ed377f54 Mon Sep 17 00:00:00 2001 From: andrew farquharson <2562-andrewfarq@users.noreply.drupalcode.org> Date: Mon, 27 Jan 2025 06:26:57 +0000 Subject: [PATCH 5/7] Edit RssResponseCdataTest.php PHPSTAN --- .../Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php b/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php index 582a357ae85c..310ab840d763 100644 --- a/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php +++ b/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php @@ -134,9 +134,6 @@ public function testOnResponse(string $content, string $expected_content): void ]) ); - $configFactoryMock = $this->createMock(ConfigFactoryInterface::class); - $configFactoryMock->method('get')->willReturn($configMock); - // Mock the RendererInterface. $rendererMock = $this->createMock(RendererInterface::class); $rendererMock->method('render')->willReturn('<rendered output>'); -- GitLab From 26dec8402846e702da5dcd3cffb4a5981b1cd335 Mon Sep 17 00:00:00 2001 From: andrew farquharson <2562-andrewfarq@users.noreply.drupalcode.org> Date: Mon, 27 Jan 2025 06:36:04 +0000 Subject: [PATCH 6/7] Edit RssResponseCdataTest.php PHPSTAN --- .../Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php b/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php index 310ab840d763..27f5a7609288 100644 --- a/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php +++ b/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php @@ -133,7 +133,8 @@ public function testOnResponse(string $content, string $expected_content): void 'Content-Type' => 'application/rss+xml', ]) ); - + + $configFactoryMock = $this->createMock(ConfigFactoryInterface::class); // Mock the RendererInterface. $rendererMock = $this->createMock(RendererInterface::class); $rendererMock->method('render')->willReturn('<rendered output>'); -- GitLab From ffe0ff942caba5a11913ed817e5737c4535ee438 Mon Sep 17 00:00:00 2001 From: andrew farquharson <2562-andrewfarq@users.noreply.drupalcode.org> Date: Mon, 27 Jan 2025 07:02:31 +0000 Subject: [PATCH 7/7] Edit RssResponseCdataTest.php --- .../Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php b/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php index 27f5a7609288..2c5884b48208 100644 --- a/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php +++ b/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseCdataTest.php @@ -133,7 +133,6 @@ public function testOnResponse(string $content, string $expected_content): void 'Content-Type' => 'application/rss+xml', ]) ); - $configFactoryMock = $this->createMock(ConfigFactoryInterface::class); // Mock the RendererInterface. $rendererMock = $this->createMock(RendererInterface::class); -- GitLab