Explorar o código

Adding Enclosure support to Atom and RSS. Adding Podcast extension.

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@16792 44c647ce-9c0f-0410-b52a-842ac1e357ba
norm2782 %!s(int64=16) %!d(string=hai) anos
pai
achega
9a25793f5b

+ 1 - 0
library/Zend/Feed/Reader.php

@@ -686,5 +686,6 @@ class Zend_Feed_Reader
         self::registerExtension('Slash');
         self::registerExtension('WellFormedWeb');
         self::registerExtension('Thread');
+        self::registerExtension('Podcast');
     }
 }

+ 18 - 0
library/Zend/Feed/Reader/Entry/Atom.php

@@ -198,6 +198,24 @@ class Zend_Feed_Reader_Entry_Atom extends Zend_Feed_Reader_Entry_Abstract implem
     }
 
     /**
+     * Get the entry enclosure
+     *
+     * @return string
+     */
+    public function getEnclosure()
+    {
+        if (array_key_exists('enclosure', $this->_data)) {
+            return $this->_data['enclosure'];
+        }
+
+        $enclosure = $this->_atom->getEnclosure();
+
+        $this->_data['enclosure'] = $enclosure;
+
+        return $this->_data['enclosure'];
+    }
+
+    /**
      * Get the entry ID
      *
      * @return string

+ 7 - 10
library/Zend/Feed/Reader/Entry/Interface.php

@@ -28,16 +28,6 @@
 interface Zend_Feed_Reader_Entry_Interface
 {
     /**
-     * Constructor
-     *
-     * @param  Zend_Feed_Entry_Abstract $entry
-     * @param  int $entryKey
-     * @param  string $type
-     * @return void
-     */
-    public function __construct(DOMElement $entry, $entryKey, $type = null);
-
-    /**
      * Get the specified author
      *
      * @param  int $index
@@ -81,6 +71,13 @@ interface Zend_Feed_Reader_Entry_Interface
     public function getDescription();
 
     /**
+     * Get the entry enclosure
+     *
+     * @return stdClass
+     */
+    public function getEnclosure();
+
+    /**
      * Get the entry ID
      *
      * @return string

+ 37 - 8
library/Zend/Feed/Reader/Entry/Rss.php

@@ -214,7 +214,7 @@ class Zend_Feed_Reader_Entry_Rss extends Zend_Feed_Reader_Entry_Abstract impleme
 
         if ($list->length) {
             foreach ($list as $author) {
-                if ($this->getType() == Zend_Feed_Reader::TYPE_RSS_20 
+                if ($this->getType() == Zend_Feed_Reader::TYPE_RSS_20
                     && preg_match("/\(([^\)]+)\)/", $author->nodeValue, $matches, PREG_OFFSET_CAPTURE)
                 ) {
                     // source name from RSS 2.0 <author>
@@ -269,7 +269,7 @@ class Zend_Feed_Reader_Entry_Rss extends Zend_Feed_Reader_Entry_Abstract impleme
 
     /**
      * Get the entry's date of creation
-     * 
+     *
      * @return string
      */
     public function getDateCreated()
@@ -279,7 +279,7 @@ class Zend_Feed_Reader_Entry_Rss extends Zend_Feed_Reader_Entry_Abstract impleme
 
     /**
      * Get the entry's date of modification
-     * 
+     *
      * @return string
      */
     public function getDateModified()
@@ -291,7 +291,7 @@ class Zend_Feed_Reader_Entry_Rss extends Zend_Feed_Reader_Entry_Abstract impleme
         $dateModified = null;
         $date = null;
 
-        if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10 
+        if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10
             && $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090
         ) {
             $dateModified = $this->_xpath->evaluate('string('.$this->_xpathQueryRss.'/pubDate)');
@@ -343,7 +343,7 @@ class Zend_Feed_Reader_Entry_Rss extends Zend_Feed_Reader_Entry_Abstract impleme
 
         $description = null;
 
-        if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10 
+        if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10
             && $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090
         ) {
             $description = $this->_xpath->evaluate('string('.$this->_xpathQueryRss.'/description)');
@@ -371,6 +371,35 @@ class Zend_Feed_Reader_Entry_Rss extends Zend_Feed_Reader_Entry_Abstract impleme
     }
 
     /**
+     * Get the entry enclosure
+     *
+     * @return string
+     */
+    public function getEnclosure()
+    {
+        if (array_key_exists('enclosure', $this->_data)) {
+            return $this->_data['enclosure'];
+        }
+
+        $enclosure = null;
+
+        if ($this->getType() == Zend_Feed_Reader::TYPE_RSS_20) {
+            $nodeList = $this->_xpath->query($this->_xpathQueryRss . '/enclosure');
+
+            if ($nodeList->length > 0) {
+                $enclosure = new stdClass();
+                $enclosure->url    = $nodeList->item(0)->getAttribute('url');
+                $enclosure->length = $nodeList->item(0)->getAttribute('length');
+                $enclosure->type   = $nodeList->item(0)->getAttribute('type');
+            }
+        }
+
+        $this->_data['enclosure'] = $enclosure;
+
+        return $this->_data['enclosure'];
+    }
+
+    /**
      * Get the entry ID
      *
      * @return string
@@ -383,7 +412,7 @@ class Zend_Feed_Reader_Entry_Rss extends Zend_Feed_Reader_Entry_Abstract impleme
 
         $id = null;
 
-        if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10 
+        if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10
             && $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090
         ) {
             $id = $this->_xpath->evaluate('string('.$this->_xpathQueryRss.'/guid)');
@@ -487,7 +516,7 @@ class Zend_Feed_Reader_Entry_Rss extends Zend_Feed_Reader_Entry_Abstract impleme
 
         $title = null;
 
-        if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10 
+        if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10
             && $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090
         ) {
             $title = $this->_xpath->evaluate('string('.$this->_xpathQueryRss.'/title)');
@@ -555,7 +584,7 @@ class Zend_Feed_Reader_Entry_Rss extends Zend_Feed_Reader_Entry_Abstract impleme
 
         $commentlink = null;
 
-        if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10 
+        if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10
             && $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090
         ) {
             $commentlink = $this->_xpath->evaluate('string('.$this->_xpathQueryRss.'/comments)');

+ 29 - 2
library/Zend/Feed/Reader/Extension/Atom/Entry.php

@@ -40,7 +40,7 @@ require_once 'Zend/Date.php';
  * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  * @license    http://framework.zend.com/license/new-bsd     New BSD License
  */
-class Zend_Feed_Reader_Extension_Atom_Entry 
+class Zend_Feed_Reader_Extension_Atom_Entry
     extends Zend_Feed_Reader_Extension_EntryAbstract
 {
 	/**
@@ -210,6 +210,33 @@ class Zend_Feed_Reader_Extension_Atom_Entry
     }
 
     /**
+     * Get the entry enclosure
+     *
+     * @return string
+     */
+    public function getEnclosure()
+    {
+        if (array_key_exists('enclosure', $this->_data)) {
+            return $this->_data['enclosure'];
+        }
+
+        $enclosure = null;
+
+        $nodeList = $this->_xpath->query($this->getXpathPrefix() . '/atom:link[@rel="enclosure"]');
+
+        if ($nodeList->length > 0) {
+            $enclosure = new stdClass();
+            $enclosure->url    = $nodeList->item(0)->getAttribute('href');
+            $enclosure->length = $nodeList->item(0)->getAttribute('length');
+            $enclosure->type   = $nodeList->item(0)->getAttribute('type');
+        }
+
+        $this->_data['enclosure'] = $enclosure;
+
+        return $this->_data['enclosure'];
+    }
+
+    /**
      * Get the entry ID
      *
      * @return string
@@ -442,7 +469,7 @@ class Zend_Feed_Reader_Extension_Atom_Entry
      */
     protected function _registerNamespaces()
     {
-        if ($this->getType() == Zend_Feed_Reader::TYPE_ATOM_10 
+        if ($this->getType() == Zend_Feed_Reader::TYPE_ATOM_10
             || $this->getType() == Zend_Feed_Reader::TYPE_ATOM_03
         ) {
             return; // pre-registered at Feed level

+ 202 - 0
library/Zend/Feed/Reader/Extension/Podcast/Entry.php

@@ -0,0 +1,202 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Feed_Reader
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Feed_Reader
+ */
+require_once 'Zend/Feed/Reader.php';
+
+/**
+ * @see Zend_Feed_Reader_Extension_EntryAbstract
+ */
+require_once 'Zend/Feed/Reader/Extension/EntryAbstract.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Feed_Reader
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Feed_Reader_Extension_Podcast_Entry extends Zend_Feed_Reader_Extension_EntryAbstract
+{
+    /**
+     * Get the entry author
+     *
+     * @return string
+     */
+    public function getCastAuthor()
+    {
+        if (isset($this->_data['author'])) {
+            return $this->_data['author'];
+        }
+
+        $author = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:author)');
+
+        if (!$author) {
+            $author = null;
+        }
+
+        $this->_data['author'] = $author;
+
+        return $this->_data['author'];
+    }
+
+    /**
+     * Get the entry block
+     *
+     * @return string
+     */
+    public function getBlock()
+    {
+        if (isset($this->_data['block'])) {
+            return $this->_data['block'];
+        }
+
+        $block = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:block)');
+
+        if (!$block) {
+            $block = null;
+        }
+
+        $this->_data['block'] = $block;
+
+        return $this->_data['block'];
+    }
+
+    /**
+     * Get the entry duration
+     *
+     * @return string
+     */
+    public function getDuration()
+    {
+        if (isset($this->_data['duration'])) {
+            return $this->_data['duration'];
+        }
+
+        $duration = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:duration)');
+
+        if (!$duration) {
+            $duration = null;
+        }
+
+        $this->_data['duration'] = $duration;
+
+        return $this->_data['duration'];
+    }
+
+    /**
+     * Get the entry explicit
+     *
+     * @return string
+     */
+    public function getExplicit()
+    {
+        if (isset($this->_data['explicit'])) {
+            return $this->_data['explicit'];
+        }
+
+        $explicit = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:explicit)');
+
+        if (!$explicit) {
+            $explicit = null;
+        }
+
+        $this->_data['explicit'] = $explicit;
+
+        return $this->_data['explicit'];
+    }
+
+    /**
+     * Get the entry keywords
+     *
+     * @return string
+     */
+    public function getKeywords()
+    {
+        if (isset($this->_data['keywords'])) {
+            return $this->_data['keywords'];
+        }
+
+        $keywords = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:keywords)');
+
+        if (!$keywords) {
+            $keywords = null;
+        }
+
+        $this->_data['keywords'] = $keywords;
+
+        return $this->_data['keywords'];
+    }
+
+    /**
+     * Get the entry subtitle
+     *
+     * @return string
+     */
+    public function getSubtitle()
+    {
+        if (isset($this->_data['subtitle'])) {
+            return $this->_data['subtitle'];
+        }
+
+        $subtitle = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:subtitle)');
+
+        if (!$subtitle) {
+            $subtitle = null;
+        }
+
+        $this->_data['subtitle'] = $subtitle;
+
+        return $this->_data['subtitle'];
+    }
+
+    /**
+     * Get the entry summary
+     *
+     * @return string
+     */
+    public function getSummary()
+    {
+        if (isset($this->_data['summary'])) {
+            return $this->_data['summary'];
+        }
+
+        $summary = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:summary)');
+
+        if (!$summary) {
+            $summary = null;
+        }
+
+        $this->_data['summary'] = $summary;
+
+        return $this->_data['summary'];
+    }
+
+    /**
+     * Register iTunes namespace
+     *
+     */
+    protected function _registerNamespaces()
+    {
+        $this->_xpath->registerNamespace('itunes', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
+    }
+}

+ 293 - 0
library/Zend/Feed/Reader/Extension/Podcast/Feed.php

@@ -0,0 +1,293 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Feed_Reader
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Feed_Reader_Extension_FeedAbstract
+ */
+require_once 'Zend/Feed/Reader/Extension/FeedAbstract.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Feed_Reader
+ * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Feed_Reader_Extension_Podcast_Feed extends Zend_Feed_Reader_Extension_FeedAbstract
+{
+    /**
+     * Get the entry author
+     *
+     * @return string
+     */
+    public function getCastAuthor()
+    {
+        if (isset($this->_data['author'])) {
+            return $this->_data['author'];
+        }
+
+        $author = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:author)');
+
+        if (!$author) {
+            $author = null;
+        }
+
+        $this->_data['author'] = $author;
+
+        return $this->_data['author'];
+    }
+
+    /**
+     * Get the entry block
+     *
+     * @return string
+     */
+    public function getBlock()
+    {
+        if (isset($this->_data['block'])) {
+            return $this->_data['block'];
+        }
+
+        $block = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:block)');
+
+        if (!$block) {
+            $block = null;
+        }
+
+        $this->_data['block'] = $block;
+
+        return $this->_data['block'];
+    }
+
+    /**
+     * Get the entry category
+     *
+     * @return string
+     */
+    public function getCategories()
+    {
+        if (isset($this->_data['categories'])) {
+            return $this->_data['categories'];
+        }
+
+        $categoryList = $this->_xpath->query($this->getXpathPrefix() . '/itunes:category');
+
+        $categories = array();
+
+        if ($categoryList->length > 0) {
+            foreach ($categoryList as $node) {
+                $children = null;
+
+                if ($node->childNodes->length > 0) {
+                    $children = array();
+
+                    foreach ($node->childNodes as $childNode) {
+                        if (!($childNode instanceof DOMText)) {
+                            $children[$childNode->getAttribute('text')] = null;
+                        }
+                    }
+                }
+
+                $categories[$node->getAttribute('text')] = $children;
+            }
+        }
+
+
+        if (!$categories) {
+            $categories = null;
+        }
+
+        $this->_data['categories'] = $categories;
+
+        return $this->_data['categories'];
+    }
+
+    /**
+     * Get the entry explicit
+     *
+     * @return string
+     */
+    public function getExplicit()
+    {
+        if (isset($this->_data['explicit'])) {
+            return $this->_data['explicit'];
+        }
+
+        $explicit = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:explicit)');
+
+        if (!$explicit) {
+            $explicit = null;
+        }
+
+        $this->_data['explicit'] = $explicit;
+
+        return $this->_data['explicit'];
+    }
+
+    /**
+     * Get the entry image
+     *
+     * @return string
+     */
+    public function getImage()
+    {
+        if (isset($this->_data['image'])) {
+            return $this->_data['image'];
+        }
+
+        $image = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:image/@href)');
+
+        if (!$image) {
+            $image = null;
+        }
+
+        $this->_data['image'] = $image;
+
+        return $this->_data['image'];
+    }
+
+    /**
+     * Get the entry keywords
+     *
+     * @return string
+     */
+    public function getKeywords()
+    {
+        if (isset($this->_data['keywords'])) {
+            return $this->_data['keywords'];
+        }
+
+        $keywords = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:keywords)');
+
+        if (!$keywords) {
+            $keywords = null;
+        }
+
+        $this->_data['keywords'] = $keywords;
+
+        return $this->_data['keywords'];
+    }
+
+    /**
+     * Get the entry's new feed url
+     *
+     * @return string
+     */
+    public function getNewFeedUrl()
+    {
+        if (isset($this->_data['new-feed-url'])) {
+            return $this->_data['new-feed-url'];
+        }
+
+        $newFeedUrl = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:new-feed-url)');
+
+        if (!$newFeedUrl) {
+            $newFeedUrl = null;
+        }
+
+        $this->_data['new-feed-url'] = $newFeedUrl;
+
+        return $this->_data['new-feed-url'];
+    }
+
+    /**
+     * Get the entry owner
+     *
+     * @return string
+     */
+    public function getOwner()
+    {
+        if (isset($this->_data['owner'])) {
+            return $this->_data['owner'];
+        }
+
+        $owner = null;
+
+        $email = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:owner/itunes:email)');
+        $name  = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:owner/itunes:name)');
+
+        if (!empty($email)) {
+            $owner = $email . (empty($name) ? '' : ' (' . $name . ')');
+        } else if (!empty($name)) {
+            $owner = $name;
+        }
+
+        if (!$owner) {
+            $owner = null;
+        }
+
+        $this->_data['owner'] = $owner;
+
+        return $this->_data['owner'];
+    }
+
+    /**
+     * Get the entry subtitle
+     *
+     * @return string
+     */
+    public function getSubtitle()
+    {
+        if (isset($this->_data['subtitle'])) {
+            return $this->_data['subtitle'];
+        }
+
+        $subtitle = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:subtitle)');
+
+        if (!$subtitle) {
+            $subtitle = null;
+        }
+
+        $this->_data['subtitle'] = $subtitle;
+
+        return $this->_data['subtitle'];
+    }
+
+    /**
+     * Get the entry summary
+     *
+     * @return string
+     */
+    public function getSummary()
+    {
+        if (isset($this->_data['summary'])) {
+            return $this->_data['summary'];
+        }
+
+        $summary = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:summary)');
+
+        if (!$summary) {
+            $summary = null;
+        }
+
+        $this->_data['summary'] = $summary;
+
+        return $this->_data['summary'];
+    }
+
+    /**
+     * Register iTunes namespace
+     *
+     */
+    protected function _registerNamespaces()
+    {
+        $this->_xpath->registerNamespace('itunes', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
+    }
+}

+ 33 - 0
tests/Zend/Feed/Reader/Entry/AtomTest.php

@@ -183,6 +183,39 @@ class Zend_Feed_Reader_Entry_AtomTest extends PHPUnit_Framework_TestCase
     }
 
     /**
+     * Get enclosure
+     */
+    public function testGetsEnclosureFromAtom03()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath.'/enclosure/plain/atom03.xml')
+        );
+        $entry = $feed->current();
+
+        $expected = new stdClass();
+        $expected->url    = 'http://www.example.org/myaudiofile.mp3';
+        $expected->length = '1234';
+        $expected->type   = 'audio/mpeg';
+
+        $this->assertEquals($expected, $entry->getEnclosure());
+    }
+
+    public function testGetsEnclosureFromAtom10()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath.'/enclosure/plain/atom10.xml')
+        );
+        $entry = $feed->current();
+
+        $expected = new stdClass();
+        $expected->url    = 'http://www.example.org/myaudiofile.mp3';
+        $expected->length = '1234';
+        $expected->type   = 'audio/mpeg';
+
+        $this->assertEquals($expected, $entry->getEnclosure());
+    }
+
+    /**
      * Get Content (Unencoded Text)
      */
     public function testGetsContentFromAtom03()

+ 27 - 0
tests/Zend/Feed/Reader/Entry/RssTest.php

@@ -1385,6 +1385,33 @@ class Zend_Feed_Reader_Entry_RssTest extends PHPUnit_Framework_TestCase
     }
 
     /**
+     * Get enclosure
+     */
+    public function testGetsEnclosureFromRss20()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath.'/enclosure/plain/rss20.xml')
+        );
+        $entry = $feed->current();
+
+        $expected = new stdClass();
+        $expected->url    = 'http://www.scripting.com/mp3s/weatherReportSuite.mp3';
+        $expected->length = '12216320';
+        $expected->type   = 'audio/mpeg';
+
+        $this->assertEquals($expected, $entry->getEnclosure());
+    }
+
+    public function testGetsEnclosureFromRss10()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath.'/enclosure/plain/rss10.xml')
+        );
+        $entry = $feed->current();
+        $this->assertEquals(null, $entry->getEnclosure());
+    }
+
+    /**
      * Get Content (Unencoded Text)
      */
     public function testGetsContentFromRss20()

+ 6 - 0
tests/Zend/Feed/Reader/Entry/_files/Atom/enclosure/plain/atom03.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<feed version="0.3" xmlns="http://purl.org/atom/ns#">
+    <entry>
+        <link rel="enclosure" type="audio/mpeg" title="MP3" href="http://www.example.org/myaudiofile.mp3" length="1234" />
+    </entry>
+</feed>

+ 6 - 0
tests/Zend/Feed/Reader/Entry/_files/Atom/enclosure/plain/atom10.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom">
+    <entry>
+        <link rel="enclosure" type="audio/mpeg" title="MP3" href="http://www.example.org/myaudiofile.mp3" length="1234" />
+    </entry>
+</feed>

+ 9 - 0
tests/Zend/Feed/Reader/Entry/_files/Rss/enclosure/plain/rss10.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<rdf:RDF
+    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+    xmlns="http://purl.org/rss/1.0/">
+    <channel>
+	   <item>
+	   </item>
+    </channel>
+</rdf:RDF>

+ 8 - 0
tests/Zend/Feed/Reader/Entry/_files/Rss/enclosure/plain/rss20.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<rss version="2.0">
+    <channel>
+    	<item>
+            <enclosure url="http://www.scripting.com/mp3s/weatherReportSuite.mp3" length="12216320" type="audio/mpeg" />
+		</item>
+    </channel>
+</rss>

+ 254 - 0
tests/Zend/Feed/Reader/Integration/PodcastRss2Test.php

@@ -0,0 +1,254 @@
+<?php
+
+require_once dirname(__FILE__) . '/../../../../TestHelper.php';
+require_once 'PHPUnit/Framework/TestCase.php';
+require_once 'Zend/Feed/Reader.php';
+
+class Zend_Feed_Reader_Integration_PodcastRss2Test extends PHPUnit_Framework_TestCase
+{
+
+    protected $_feedSamplePath = null;
+
+    public function setup()
+    {
+        $this->_feedSamplePath = dirname(__FILE__) . '/_files/podcast.xml';
+    }
+
+    /**
+     * Feed level testing
+     */
+
+    public function testGetsNewFeedUrl()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $this->assertEquals('http://newlocation.com/example.rss', $feed->getNewFeedUrl());
+    }
+
+    public function testGetsOwner()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $this->assertEquals('john.doe@example.com (John Doe)', $feed->getOwner());
+    }
+
+    public function testGetsCategories()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $this->assertEquals(array(
+            'Technology' => array(
+                'Gadgets' => null
+            ),
+            'TV & Film' => null
+        ), $feed->getCategories());
+    }
+
+    public function testGetsTitle()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $this->assertEquals('All About Everything', $feed->getTitle());
+    }
+
+    public function testGetsCastAuthor()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $this->assertEquals('John Doe', $feed->getCastAuthor());
+    }
+
+    public function testGetsFeedBlock()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $this->assertEquals('no', $feed->getBlock());
+    }
+
+    public function testGetsCopyright()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $this->assertEquals('℗ & © 2005 John Doe & Family', $feed->getCopyright());
+    }
+
+    public function testGetsDescription()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $this->assertEquals('All About Everything is a show about everything.
+            Each week we dive into any subject known to man and talk
+            about it as much as we can. Look for our Podcast in the
+            iTunes Store', $feed->getDescription());
+    }
+
+    public function testGetsLanguage()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $this->assertEquals('en-us', $feed->getLanguage());
+    }
+
+    public function testGetsLink()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $this->assertEquals('http://www.example.com/podcasts/everything/index.html', $feed->getLink());
+    }
+
+    public function testGetsEncoding()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $this->assertEquals('UTF-8', $feed->getEncoding());
+    }
+
+    public function testGetsFeedExplicit()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $this->assertEquals('yes', $feed->getExplicit());
+    }
+
+    public function testGetsEntryCount()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $this->assertEquals(3, $feed->count());
+    }
+
+    public function testGetsImage()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $this->assertEquals('http://example.com/podcasts/everything/AllAboutEverything.jpg', $feed->getImage());
+    }
+
+    /**
+     * Entry level testing
+     */
+
+    public function testGetsEntryBlock()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $entry = $feed->current();
+        $this->assertEquals('yes', $entry->getBlock());
+    }
+
+    public function testGetsEntryId()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $entry = $feed->current();
+        $this->assertEquals('http://example.com/podcasts/archive/aae20050615.m4a', $entry->getId());
+    }
+
+    public function testGetsEntryTitle()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $entry = $feed->current();
+        $this->assertEquals('Shake Shake Shake Your Spices', $entry->getTitle());
+    }
+
+    public function testGetsEntryCastAuthor()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $entry = $feed->current();
+        $this->assertEquals('John Doe', $entry->getCastAuthor());
+    }
+
+    public function testGetsEntryExplicit()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $entry = $feed->current();
+        $this->assertEquals('no', $entry->getExplicit());
+    }
+
+    public function testGetsSubtitle()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $entry = $feed->current();
+        $this->assertEquals('A short primer on table spices
+            ', $entry->getSubtitle());
+    }
+
+    public function testGetsSummary()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $entry = $feed->current();
+        $this->assertEquals('This week we talk about salt and pepper
+                shakers, comparing and contrasting pour rates,
+                construction materials, and overall aesthetics. Come and
+                join the party!', $entry->getSummary());
+    }
+
+    public function testGetsDuration()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $entry = $feed->current();
+        $this->assertEquals('7:04', $entry->getDuration());
+    }
+
+    public function testGetsKeywords()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $entry = $feed->current();
+        $this->assertEquals('salt, pepper, shaker, exciting
+            ', $entry->getKeywords());
+    }
+
+    public function testGetsEntryEncoding()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $entry = $feed->current();
+        $this->assertEquals('UTF-8', $entry->getEncoding());
+    }
+
+    public function testGetsEnclosure()
+    {
+        $feed = Zend_Feed_Reader::importString(
+            file_get_contents($this->_feedSamplePath)
+        );
+        $entry = $feed->current();
+
+        $expected = new stdClass();
+        $expected->url    = 'http://example.com/podcasts/everything/AllAboutEverythingEpisode3.m4a';
+        $expected->length = '8727310';
+        $expected->type   = 'audio/x-m4a';
+
+        $this->assertEquals($expected, $entry->getEnclosure());
+    }
+}

+ 92 - 0
tests/Zend/Feed/Reader/Integration/_files/podcast.xml

@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
+    version="2.0">
+
+    <channel>
+        <title>All About Everything</title>
+        <link>http://www.example.com/podcasts/everything/index.html</link>
+        <language>en-us</language>
+        <copyright>&#x2117; &amp; &#xA9; 2005 John Doe &amp; Family</copyright>
+		<itunes:explicit>yes</itunes:explicit>
+		<itunes:block>no</itunes:block>
+        <itunes:subtitle>A show about everything</itunes:subtitle>
+        <itunes:author>John Doe</itunes:author>
+        <itunes:summary>All About Everything is a show about everything.
+            Each week we dive into any subject known to man and talk
+            about it as much as we can. Look for our Podcast in the
+            iTunes Store</itunes:summary>
+        <description>All About Everything is a show about everything.
+            Each week we dive into any subject known to man and talk
+            about it as much as we can. Look for our Podcast in the
+            iTunes Store</description>
+        <itunes:owner>
+            <itunes:name>John Doe</itunes:name>
+            <itunes:email>john.doe@example.com</itunes:email>
+        </itunes:owner>
+		<itunes:new-feed-url>http://newlocation.com/example.rss</itunes:new-feed-url>
+        <itunes:image
+            href="http://example.com/podcasts/everything/AllAboutEverything.jpg" />
+        <itunes:category text="Technology">
+            <itunes:category text="Gadgets" />
+        </itunes:category>
+        <itunes:category text="TV &amp; Film" />
+
+        <item>
+            <title>Shake Shake Shake Your Spices</title>
+			<itunes:explicit>no</itunes:explicit>
+            <itunes:author>John Doe</itunes:author>
+			<itunes:block>yes</itunes:block>
+            <itunes:subtitle>A short primer on table spices
+            </itunes:subtitle>
+            <itunes:summary>This week we talk about salt and pepper
+                shakers, comparing and contrasting pour rates,
+                construction materials, and overall aesthetics. Come and
+                join the party!</itunes:summary>
+            <enclosure
+                url="http://example.com/podcasts/everything/AllAboutEverythingEpisode3.m4a"
+                length="8727310" type="audio/x-m4a" />
+            <guid>http://example.com/podcasts/archive/aae20050615.m4a</guid>
+            <pubDate>Wed, 15 Jun 2005 19:00:00 GMT</pubDate>
+            <itunes:duration>7:04</itunes:duration>
+            <itunes:keywords>salt, pepper, shaker, exciting
+            </itunes:keywords>
+        </item>
+
+        <item>
+            <title>Socket Wrench Shootout</title>
+            <itunes:author>Jane Doe</itunes:author>
+            <itunes:subtitle>Comparing socket wrenches is fun!
+            </itunes:subtitle>
+            <itunes:summary>This week we talk about metric vs. old
+                english socket wrenches. Which one is better? Do you
+                really need both? Get all of your answers here.
+            </itunes:summary>
+            <enclosure
+                url="http://example.com/podcasts/everything/AllAboutEverythingEpisode2.mp3"
+                length="5650889" type="audio/mpeg" />
+            <guid>http://example.com/podcasts/archive/aae20050608.mp3</guid>
+            <pubDate>Wed, 8 Jun 2005 19:00:00 GMT</pubDate>
+            <itunes:duration>4:34</itunes:duration>
+            <itunes:keywords>metric, socket, wrenches, tool
+            </itunes:keywords>
+        </item>
+
+        <item>
+            <title>Red, Whine, &amp; Blue</title>
+            <itunes:author>Various</itunes:author>
+            <itunes:subtitle>Red + Blue != Purple</itunes:subtitle>
+            <itunes:summary>This week we talk about surviving in a Red
+                state if you are a Blue person. Or vice versa.
+            </itunes:summary>
+            <enclosure
+                url="http://example.com/podcasts/everything/AllAboutEverythingEpisode1.mp3"
+                length="4989537" type="audio/mpeg" />
+            <guid>http://example.com/podcasts/archive/aae20050601.mp3</guid>
+            <pubDate>Wed, 1 Jun 2005 19:00:00 GMT</pubDate>
+            <itunes:duration>3:59</itunes:duration>
+            <itunes:keywords>politics, red, blue, state
+            </itunes:keywords>
+        </item>
+
+    </channel>
+</rss>