Creating Podcast XML from Drupal content

I needed to create some podcasts for Kansas Public Radio, which uses the Drupal Content Management System (CMS). I couldn't find a satisfactory Drupal module that could create the RSS data that iTunes needs, so I had to come up with my own solution. IIRC, Drupal Feeds would have worked great but iTunes needs specific XML tags (i.e. <itunes:description>, <itunes:category>, etc) that Drupal Feeds couldn't provide. I also dried Drupal Views PHP but it was too buggy and I also couldn't get the code to output outside of the template.

My solution was to create a stand alone PHP page that bootstraps Drupal, then I could do anything I wanted with the data. 

The first step was to create a new view in Drupal that the PHP could execute. Much easier than writing the SQL manually. No need to reinvent the wheel. 

Then I created a new PHP file called kpr-presents.php and I put it in a directory named /widgets/podcats. 

Before the PHP works on the tagging the data, it can just output the static data at the beginning of the XML document.

  1.  <?php
  2. // set the content type to XML
  3. header("Content-type: text/xml");
  4.  
  5. // it likes to be echo'd for some reason...
  6. echo '<?xml version="1.0" encoding="UTF-8"?>'."\r\n";;
  7. ?>
  8. <rss xmlns:itunes="<a href="http://www.itunes.com/dtds/podcast-1.0.dtd"">http://www.itunes.com/dtds/podcast-1.0.dtd"</a> version="2.0">
  9.     <channel>
  10.         <title>KPR Presents</title>
  11.         <link><a href="http://kansaspublicradio.org/kpr-news/kpr%20presents</link>
  12. ">http://kansaspublicradio.org/kpr-news/kpr%20presents</link>
  13. </a>        <language>en-us</language>
  14.         <copyright>&#x2117; &amp; &#xA9; 2015 Kansas Public Radio</copyright>
  15.         <itunes:subtitle>Join Kay McIntyre on Kansas Public Radio&#39;s weekly talk-radio show.</itunes:subtitle>
  16.         <itunes:author>Kansas Public Radio</itunes:author>
  17.         <itunes:summary>KPR Presents is an opportunity to showcase high-profile, thought-provoking lectures, discussions and dialogues recorded throughout the region. There are so many fascinating people who come to this area, everyone from Supreme Court Justice Sonya Sotomayor to syndicated columnist Leonard Pitts. KPR Presents is a great way to share some of those lectures with our listeners. We have also been able to expand the program to cover a broad range of topics, including the Kansas Sesquicentennial, the National Day of Listening and the Kansas Reads program sponsored by the State Library of Kansas, just to name a few.</itunes:summary>
  18.         <description>KPR Presents is an opportunity to showcase high-profile, thought-provoking lectures, discussions and dialogues recorded throughout the region. There are so many fascinating people who come to this area, everyone from Supreme Court Justice Sonya Sotomayor to syndicated columnist Leonard Pitts. KPR Presents is a great way to share some of those lectures with our listeners. We have also been able to expand the program to cover a broad range of topics, including the Kansas Sesquicentennial, the National Day of Listening and the Kansas Reads program sponsored by the State Library of Kansas, just to name a few.</description>
  19.         <itunes:owner>
  20.             <itunes:name>Kansas Public Radio</itunes:name>
  21.             <itunes:email><a href="mailto:kprdeveloper@gmail.com">kprdeveloper@gmail.com</a></itunes:email>
  22.         </itunes:owner>
  23.         <itunes:image href="<a href="http://kansaspublicradio.org/widgets/podcasts/kpr-presents-logo_3000x3000.png"">http://kansaspublicradio.org/widgets/podcasts/kpr-presents-logo_3000x300...</a> />
  24.         <itunes:category text="Society &amp; Culture" />
  25.         <itunes:explicit>no</itunes:explicit>

Now it's time to put the power of Drupal to use. First we need to bootstrap it.

  1.  // load Drupal
  2. define('DRUPAL_ROOT', '/home3/kpr/public_html');
  3. require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
  4. drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
  5. date_default_timezone_set('America/Chicago');

Now we can use the Drupal functions to execute the View that we created earlier. Then we can parse through that data and put it into XML tags.

  1.  // load the drupal view that does all the sql work for us
  2. $view = views_get_view('podcast_data', true);
  3. $view->set_display('kpr_presents');
  4. $view->pre_execute();
  5. $view->execute();
  6.  
  7. foreach ($view->result as $item) {
  8.     $node = node_load($item->nid);
  9.    
  10.     // now do stuff with the node
  11.     //print_r($node);
  12.      
  13.     $mp3url = $node->npr_audio[LANGUAGE_NONE][0]['mp3'];
  14.    
  15.     // some things are getting duplicated, need to watch out for that, it's a no no
  16.     if (($mp3url == '') || ($mp3url == NULL)) {
  17.       continue;
  18.     }
  19.    
  20.     echo '<item>'."\r\n";
  21.     echo '    <title>'.check_plain($node->title).'</title>'."\r\n";
  22.     echo '    <itunes:subtitle>This week on KPR Presents...</itunes:subtitle>'."\r\n";
  23.     echo '    <pubDate>'.date("D, d M Y H:i:s",$node->created).' GMT</pubDate>'."\r\n";
  24.     echo '    <itunes:author>Kay McIntyre</itunes:author>'."\r\n";
  25.     echo '    <itunes:summary><![CDATA[ ' . htmlspecialchars($node->body[LANGUAGE_NONE][0]['summary']) . ' ]]></itunes:summary>'."\r\n";
  26.     echo '    <itunes:image href="'.str_replace('/widgets/podcasts', '', file_create_url($node->field_image[LANGUAGE_NONE][0]['uri'])).'" />'."\r\n";
  27.    
  28.     // <enclosure> is the media of the podcast
  29.     // length is the file size in bytes
  30.     $bytes = curl_get_file_size($mp3url);
  31.     echo '    <enclosure url="'.$mp3url.'" length="'.$bytes.'" type="audio/mpeg" />'."\r\n";
  32.    
  33.     $duration = $node->npr_audio[LANGUAGE_NONE][0]["duration"];
  34.     // actually I don't think we NEED to worry about what format it's in, itunes accept either seconds or hh:mm:ss formats.
  35.     //if (!strpos($duration, ':')) {
  36.     //  // if no colon, then it's in seconds. We need to covert it to human readable format.
  37.     //  $duration = gmdate("i:s", $duration);
  38.     //}
  39.     if ($duration == '') $duration = '59:00'; // most KPR Presents shows are 59 minutes long
  40.     echo '    <itunes:duration>'.$duration.'</itunes:duration>'."\r\n";
  41.    
  42.     // guid can just be the url since that's unique
  43.     echo '    <guid>$node->nid.'</guid>'."\r\n";
  44.    
  45.    echo '</item>'."\r\n";  
  46. }

I should explain that this PHP code is specific to my website, which saves the MP3 URL in a field called NPR Audio. You can download and install the NPR Drupal module which provides this field and is pretty easy to use.

AttachmentSize
Plain text icon kpr-presents.php6.91 KB
File example podcast XML3.63 KB