RssResponseRelativeUrlFilter.php 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. <?php
  2. namespace Drupal\Core\EventSubscriber;
  3. use Drupal\Component\Utility\Html;
  4. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  5. use Symfony\Component\HttpFoundation\Request;
  6. use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
  7. use Symfony\Component\HttpKernel\KernelEvents;
  8. /**
  9. * Subscribes to filter RSS responses, to make relative URIs absolute.
  10. */
  11. class RssResponseRelativeUrlFilter implements EventSubscriberInterface {
  12. /**
  13. * Converts relative URLs to absolute URLs.
  14. *
  15. * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
  16. * The response event.
  17. */
  18. public function onResponse(FilterResponseEvent $event) {
  19. // Only care about RSS responses.
  20. if (stripos($event->getResponse()->headers->get('Content-Type'), 'application/rss+xml') === FALSE) {
  21. return;
  22. }
  23. $response = $event->getResponse();
  24. $response->setContent($this->transformRootRelativeUrlsToAbsolute($response->getContent(), $event->getRequest()));
  25. }
  26. /**
  27. * Converts all root-relative URLs to absolute URLs in RSS markup.
  28. *
  29. * Does not change any existing protocol-relative or absolute URLs.
  30. *
  31. * @param string $rss_markup
  32. * The RSS markup to update.
  33. * @param \Symfony\Component\HttpFoundation\Request $request
  34. * The current request.
  35. *
  36. * @return string
  37. * The updated RSS markup.
  38. */
  39. protected function transformRootRelativeUrlsToAbsolute($rss_markup, Request $request) {
  40. $rss_dom = new \DOMDocument();
  41. // Load the RSS, if there are parsing errors, abort and return the unchanged
  42. // markup.
  43. $previous_value = libxml_use_internal_errors(TRUE);
  44. $rss_dom->loadXML($rss_markup);
  45. $errors = libxml_get_errors();
  46. libxml_use_internal_errors($previous_value);
  47. if ($errors) {
  48. return $rss_markup;
  49. }
  50. // Invoke Html::transformRootRelativeUrlsToAbsolute() on all HTML content
  51. // embedded in this RSS feed.
  52. foreach ($rss_dom->getElementsByTagName('description') as $node) {
  53. $html_markup = $node->nodeValue;
  54. if (!empty($html_markup)) {
  55. $node->nodeValue = Html::transformRootRelativeUrlsToAbsolute($html_markup, $request->getSchemeAndHttpHost());
  56. }
  57. }
  58. return $rss_dom->saveXML();
  59. }
  60. /**
  61. * {@inheritdoc}
  62. */
  63. public static function getSubscribedEvents() {
  64. // Should run after any other response subscriber that modifies the markup.
  65. // @see \Drupal\Core\EventSubscriber\ActiveLinkResponseFilter
  66. $events[KernelEvents::RESPONSE][] = ['onResponse', -512];
  67. return $events;
  68. }
  69. }