Drupal
min read

Drupal Podcast Feeds Integration: A Step-by-Step Guide

Drupal Podcast Feeds Integration: A Step-by-Step Guide
Table of contents

Managing and importing podcast feeds into your Drupal website can greatly enhance your content diversity and keep your audience engaged. In this guide, we'll walk through the process of setting up a podcast feed integration using Drupal, covering important aspects such as parsing feed data, creating a custom parser, and saving relevant information as media entities.

Prerequisites

Before diving into the integration process, ensure you have the following elements in place:

  • Drupal website (preferably Drupal 8 or Drupal 9)
  • Feeds module installed and enabled
  • Custom module for extending Feeds functionality

Setting Up the Podcast Feed Parser

1. Create a Feed Parser

Inside your custom module directory, create a Feeds/Parser subdirectory. Within this directory, develop a custom parser class to handle the podcast feed. This class should extend the Feeds\Parser\ParserBase class.

// CustomModule/src/Feeds/Parser/CustomPodcastParser.php


use Laminas\Feed\Reader\Exception\ExceptionInterface;
use Laminas\Feed\Reader\Reader;


/**
* Defines an OPML feed parser.
*
* @FeedsParser(
*   id = "adapodcast",
*   title = @Translation("Custom Podcast"),
*   description = @Translation("Custom Podcast.")
* )
*/
class CustomPodcastParser extends SyndicationParser {


2. Implement Parsing Logic

Inside the custom parser, implement the parse() method to extract relevant data, such as podcast duration, from the feed. Additionally, use the getMappingSources() method to define the mapping source for the new podcast duration field.

// CustomModule/src/Feeds/Parser/CustomPodcastParser.php


/**
  * {@inheritdoc}
  */
 public function parse(FeedInterface $feed, FetcherResultInterface $fetcher_result, StateInterface $state) {
   if (!class_exists('Laminas\Feed\Reader\Reader')) {
     throw new \RuntimeException("The library laminas/laminas-feed is not installed. You can install it with Composer or by using the Ludwig module.");
   }


   $results = parent::parse($feed, $fetcher_result, $state);
   $raw = $fetcher_result->getRaw();


   if (!strlen(trim($raw))) {
     throw new EmptyFeedException();
   }


   try {
     $channel = Reader::importString($raw);
   }
   catch (ExceptionInterface $e) {
     $args = ['%site' => $feed->label(), '%error' => trim($e->getMessage())];
     throw new \RuntimeException("The feed from %site seems to be broken because of error $args");
   }


   foreach ($results as $result) {
     $result_array = (array) $result;
     $result_title = $result_array["title"];
     foreach ($channel as $entry) {
       $ch_title = $entry->getTitle();
       if ($result_title == $ch_title) {
         $result->duration = $entry->getDuration();
       }
     }
   }


   return $results;
 }

/**
  * {@inheritdoc}
  */
 public function getMappingSources() {
   $data = parent::getMappingSources();
   $data['duration'] = [
     'label' => $this->t('Duration'),
     'description' => $this->t('Podcast duration in minutes.'),
     'suggestions' => [
       'targets' => ['duration', 'itunes:duration'],
       'types' => ['field_item:text' => []],
     ],
   ];
   return $data;
 }

Creating the Event Subscriber

3. Event Subscriber for Presaving

Create an event subscriber within your custom module to handle presaving of entities. This subscriber should fetch relevant information, such as the podcast thumbnail and audio URL, and save it as a media entity.

// CustomModule/src/EventSubscriber/CustomPodcastEventSubscriber.php


class CustomPodcastEventSubscriber implements EventSubscriberInterface {




/**
 * Acts on presaving an entity.
 *
 * @param Drupal\feeds\Event\EntityEvent $event
 *   EntityEvent.
 */
 public function presave(EntityEvent $event) {
   $entity = $event->getEntity();
   $item = $event->getItem();
   $audio_url = $item->get('enclosures');
   if (!$audio_url) return;
    $thumbnail = $item->get('feed_image_uri');
    $alt_text = end(explode('/', rtrim($item->get('url'), '/')));
   $file_id =   $this->entityTypeManager->getStorage('file')->loadByProperties(['filename' => basename($thumbnail)]) ?: $this->saveImage($thumbnail);
    $media_id = $this->entityTypeManager->getStorage('media')->loadByProperties(['field_media_link' => $audio_url, 'field_audio_thumbnail' => $thumbnail]) ?: $this->createMedia($audio_url, $thumbnail, $file_id);
   $entity->field_podcast->setValue(['target_id' => reset($media_id)->id()]);
   $entity->setOwnerId(1);
 }
  private function createMedia($audio_url, $thumbnail, $file_id) {
   $alt_text = end(explode('/', rtrim($item->get('url'), '/')));
   $media_storage = $this->entityTypeManager->getStorage('media');
   $media = $media_storage->create(['bundle' => 'remote_audio', 'uid' => 1, 'field_media_link' => reset($audio_url), 'field_audio_thumbnail' => ['target_id' => $file_id, 'alt' => $alt_text, 'title' => $alt_text], 'thumbnail' => ['target_id' => $file_id, 'alt' => $alt_text, 'title' => $alt_text]]);
   $media->setName($alt_text)->setPublished(TRUE)->save();
   return $media;
 }
}



4. Configure Event Subscriber

Finally, configure the event subscriber to trigger the presave function when necessary. You can do this by creating a services YAML file.

# CustomModule.services.yml


services:
 custom_podcast.event_subscriber:
 class: Drupal\custom_module\EventSubscriber\CustomPodcastEventSubscriber
 tags:
 - { name: 'event_subscriber' }
 
 

Example Feed Data

Here's an example of podcast feed data for reference:

Sample Feed URL


<item>
 <title>Winter is Here!</title>
 <itunes:duration>29:47</itunes:duration>
 <!-- Additional podcast details -->
</item>


Steps to configure Feed on Drupal UI with custom parser.

Step 1: Navigate to the Feeds Page

To begin the configuration process, access the Feeds page on your Drupal site. This can be achieved by navigating to /admin/structure/feeds.

feed types

Step 2: Add a New Feed Type

Once on the Feeds page, click on "Add Feed type" to initiate the setup process for a new feed.

Step 3: Provide Feed Details

Enter the necessary details for the feed you're configuring. For example:

Name: Podcast

Fetcher: Download from URL

Parser: Custom Podcast

Processor: Node

Content Type: Podcast

These details ensure that Drupal knows how to handle the incoming feed data.

add feed type

Step 4: Save the Feed Configuration

After entering the feed details, save the feed configuration to proceed to the next steps.

Step 5: Configure Field Mapping

Navigate to the Mapping tab, where you can map the fields from your feed to corresponding Drupal fields. Here, you'll find the Duration field in the source field list. Configure the source and target fields according to your feed data, and then save the mapping settings.

mappings podcast

Step 6: Prepare for Feed Import

With the field mapping completed, your feed is now ready for import. You can proceed to the Feeds section under the Content tab (/admin/content/feed) and add a new feed.

add podcast

Step 7: Import and Verify

Initiate the import process for the added feed, and verify the imported data in the content list. This step ensures that the configured feed is successfully pulling in content according to your specifications.

fetching podcast import
content

Conclusion

By following these steps, you'll have successfully set up a podcast feed integration in Drupal. This not only allows for seamless content updates but also enhances the overall user experience on your website. Adjust the provided examples according to your specific requirements and feed structures. 

Happy podcasting!

Publish date
February 7, 2024
Last update
Written by
Artwork by
No art workers.
We'd love to talk about your business objectives