* A PHP-Based RSS and Atom Feed Framework.
* Takes the hard work out of managing a complete RSS/Atom solution.
* Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* * Neither the name of the SimplePie Team nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
* AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue
* @link http://simplepie.org/ SimplePie
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* Manages all item-related data
* Used by {@see SimplePie::get_item()} and {@see SimplePie::get_items()}
* This class can be overloaded with {@see SimplePie::set_item_class()}
* @var SimplePie_Registry
* Create a new item object
* This is usually used by {@see SimplePie::get_items} and
* {@see SimplePie::get_item}. Avoid creating this manually.
* @param SimplePie $feed Parent feed
* @param array $data Raw data
public function __construct($feed, $data)
* Set the registry handler
* This is usually used by {@see SimplePie_Registry::create}
* @param SimplePie_Registry $registry
public function set_registry(SimplePie_Registry $registry)
$this->registry = $registry;
* Get a string representation of the item
public function __toString()
return md5(serialize($this->data));
* Remove items that link back to this before destroying this object
public function __destruct()
* Get data for an item-level element
* This method allows you to get access to ANY element/attribute that is a
* sub-element of the item/entry tag.
* See {@see SimplePie::get_feed_tags()} for a description of the return value
* @see http://simplepie.org/wiki/faq/supported_xml_namespaces
* @param string $namespace The URL of the XML namespace of the elements you're trying to access
* @param string $tag Tag name
public function get_item_tags($namespace, $tag)
if (isset($this->data['child'][$namespace][$tag]))
return $this->data['child'][$namespace][$tag];
* Get the base URL value from the parent feed
public function get_base($element = array())
return $this->feed->get_base($element);
* @see SimplePie::sanitize()
* @param string $data Data to sanitize
* @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants
* @param string $base Base URL to resolve URLs against
* @return string Sanitized data
public function sanitize($data, $type, $base = '')
return $this->feed->sanitize($data, $type, $base);
* Note: this may not work as you think for multifeeds!
* @link http://simplepie.org/faq/typical_multifeed_gotchas#missing_data_from_feed
public function get_feed()
* Get the unique identifier for the item
* This is usually used when writing code to check for new items in a feed.
* Uses `<atom:id>`, `<guid>`, `<dc:identifier>` or the `about` attribute
* for RDF. If none of these are supplied (or `$hash` is true), creates an
* MD5 hash based on the permalink, title and content.
* @param boolean $hash Should we force using a hash instead of the supplied ID?
* @param string|false $fn User-supplied function to generate an hash
public function get_id($hash = false, $fn = 'md5')
if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
elseif (isset($this->data['attribs'][SIMPLEPIE_NAMESPACE_RDF]['about']))
return $this->sanitize($this->data['attribs'][SIMPLEPIE_NAMESPACE_RDF]['about'], SIMPLEPIE_CONSTRUCT_TEXT);
elseif (!is_callable($fn))
trigger_error('User-supplied function $fn must be callable', E_USER_WARNING);
return call_user_func($fn,
$this->get_permalink().$this->get_title().$this->get_content());
* Get the title of the item
* Uses `<atom:title>`, `<title>` or `<dc:title>`
* @since Beta 2 (previously called `get_item_title` since 0.8)
public function get_title()
if (!isset($this->data['title']))
if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
$this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
$this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
$this->data['title'] = null;
return $this->data['title'];
* Get the content for the item
* Prefers summaries over full content , but will return full content if a
* summary does not exist.
* To prefer full content instead, use {@see get_content}
* Uses `<atom:summary>`, `<description>`, `<dc:description>` or
* @param boolean $description_only Should we avoid falling back to the content?
public function get_description($description_only = false)
if (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary')) &&
($return = $this->sanitize($tags[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($tags[0]['attribs'])), $this->get_base($tags[0]))))
elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary')) &&
($return = $this->sanitize($tags[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($tags[0]['attribs'])), $this->get_base($tags[0]))))
elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description')) &&
($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($tags[0]))))
elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description')) &&
($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($tags[0]))))
elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description')) &&
($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)))
elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description')) &&
($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)))
elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary')) &&
($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($tags[0]))))
elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle')) &&
($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)))
elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description')) &&
($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_HTML)))
elseif (!$description_only)
return $this->get_content(true);
* Get the content for the item
* Prefers full content over summaries, but will return a summary if full
* content does not exist.
* To prefer summaries instead, use {@see get_description}
* Uses `<atom:content>` or `<content:encoded>` (RSS 1.0 Content Module)
* @param boolean $content_only Should we avoid falling back to the description?
public function get_content($content_only = false)
if (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content')) &&
($return = $this->sanitize($tags[0]['data'], $this->registry->call('Misc', 'atom_10_content_construct_type', array($tags[0]['attribs'])), $this->get_base($tags[0]))))
elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content')) &&
($return = $this->sanitize($tags[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($tags[0]['attribs'])), $this->get_base($tags[0]))))
elseif (($tags = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded')) &&
($return = $this->sanitize($tags[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($tags[0]))))
return $this->get_description(true);
* Get the media:thumbnail of the item
* Uses `<media:thumbnail>`
public function get_thumbnail()
if (!isset($this->data['thumbnail']))
if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
$this->data['thumbnail'] = $return[0]['attribs'][''];
$this->data['thumbnail'] = null;
return $this->data['thumbnail'];
* Get a category for the item
* @since Beta 3 (previously called `get_categories()` since Beta 2)
* @param int $key The category that you want to return. Remember that arrays begin with 0, not 1
* @return SimplePie_Category|null
public function get_category($key = 0)
$categories = $this->get_categories();
if (isset($categories[$key]))
return $categories[$key];
* Get all categories for the item
* Uses `<atom:category>`, `<category>` or `<dc:subject>`
* @return SimplePie_Category[]|null List of {@see SimplePie_Category} objects
public function get_categories()
foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, $type) as $category)
if (isset($category['attribs']['']['term']))
$term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
if (isset($category['attribs']['']['scheme']))
$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
if (isset($category['attribs']['']['label']))
$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
$categories[] = $this->registry->create('Category', array($term, $scheme, $label, $type));
foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, $type) as $category)
// This is really the label, but keep this as the term also for BC.
// Label will also work on retrieving because that falls back to term.
$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
if (isset($category['attribs']['']['domain']))
$scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
$categories[] = $this->registry->create('Category', array($term, $scheme, null, $type));