Apache Zeta Components Manual :: File Source for rss2.php
Source for file rss2.php
Documentation is available at rss2.php
* File containing the ezcFeedRss2 class.
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* @version //autogentag//
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* Class providing parsing and generating of RSS2 feeds.
* {@link http://www.rssboard.org/rss-specification RSS2 Specifications}.
* @version //autogentag//
* Defines the feed type of this processor.
* Defines the feed content type of this processor.
* Creates a new RSS2 processor.
* @param ezcFeed $container The feed data container used when generating
$this->feedContainer =
$container;
$this->feedType =
self::FEED_TYPE;
$this->contentType =
self::CONTENT_TYPE;
// initialize docs and pubDate with default values
if ( !isset
( $this->docs ) )
$this->docs =
'http://www.rssboard.org/rss-specification';
if ( !isset
( $this->published ) )
$this->published =
time();
* Returns an XML string from the feed information contained in this
$this->xml =
new DOMDocument( '1.0', 'utf-8' );
$this->xml->formatOutput =
1;
$rss =
$this->xml->createElement( 'rss' );
$rssVersionTag =
$this->xml->createAttribute( 'version' );
$rssVersionContent =
$this->xml->createTextNode( '2.0' );
$rssVersionTag->appendChild( $rssVersionContent );
$rss->appendChild( $rssVersionTag );
$this->channel =
$this->xml->createElement( 'channel' );
$rss->appendChild( $this->channel );
$this->root =
$this->xml->appendChild( $rss );
$this->generateRequired();
$this->generateOptional();
$this->generateFeedModules( $this->channel );
return $this->xml->saveXML();
* Returns true if the parser can parse the provided XML document object,
* @param DOMDocument $xml The XML document object to check for parseability
public static function canParse( DOMDocument $xml )
if ( $xml->documentElement->tagName !==
'rss' )
if ( !$xml->documentElement->hasAttribute( 'version' ) )
if ( !in_array( $xml->documentElement->getAttribute( 'version' ), array( '0.91', '0.92', '0.93', '0.94', '2.0' ) ) )
* Parses the provided XML document object and returns an ezcFeed object
* @throws ezcFeedParseErrorException
* If an error was encountered during parsing.
* @param DOMDocument $xml The XML document object to parse
public function parse( DOMDocument $xml )
$feed =
new ezcFeed( self::FEED_TYPE );
$rssChildren =
$xml->documentElement->childNodes;
$this->usedPrefixes =
$this->fetchUsedPrefixes( $xml );
foreach ( $rssChildren as $rssChild )
if ( $rssChild->nodeType ===
XML_ELEMENT_NODE
&&
$rssChild->tagName ===
'channel' )
foreach ( $channel->childNodes as $channelChild )
if ( $channelChild->nodeType ==
XML_ELEMENT_NODE )
$tagName =
$channelChild->tagName;
$element =
$feed->add( $tagName );
$element->text =
$channelChild->textContent;
$element =
$feed->add( $tagName );
$element->text =
$channelChild->textContent;
$element =
$feed->add( $tagName );
$element->name =
$channelChild->textContent;
$element =
$feed->add( 'author' );
$element->name =
$channelChild->textContent;
// @todo parse $name to see if it has the structure
// email@address (name) to fill the ->email field from it
$element =
$feed->add( 'webMaster' );
$element->name =
$channelChild->textContent;
// @todo parse $name to see if it has the structure
// email@address (name) to fill the ->email field from it
$element =
$feed->add( $tagName );
$element->term =
$channelChild->textContent;
if ( $channelChild->hasAttribute( 'domain' ) )
$element->scheme =
$channelChild->getAttribute( 'domain' );
$element =
$feed->add( $tagName );
$element->href =
$channelChild->textContent;
$element =
$feed->add( $tagName );
$attributes =
array( 'domain' =>
'domain', 'port' =>
'port', 'path' =>
'path',
'registerProcedure' =>
'registerProcedure', 'protocol' =>
'protocol' );
foreach ( $attributes as $name =>
$alias )
if ( $channelChild->hasAttribute( $name ) )
$element->$alias =
$channelChild->getAttribute( $name );
$feed->published =
$channelChild->textContent;
$feed->updated =
$channelChild->textContent;
$element =
$feed->add( $tagName );
$this->parseItem( $element, $channelChild );
$image =
$feed->add( 'image' );
$this->parseImage( $image, $channelChild );
$element =
$feed->add( $tagName );
$this->parseSkipHours( $element, $channelChild );
$element =
$feed->add( $tagName );
$this->parseSkipDays( $element, $channelChild );
$element =
$feed->add( $tagName );
$this->parseTextInput( $element, $channelChild );
// check if it's part of a known module/namespace
$this->parseModules( $feed, $channelChild, $tagName );
* Adds the required feed elements to the XML document being generated.
private function generateRequired()
$elements =
array( 'title', 'link', 'description' );
foreach ( $elements as $element )
foreach ( $data as $dataNode )
$this->generateMetaData( $this->channel, $element, $dataNode->href );
foreach ( $data as $dataNode )
$this->generateMetaData( $this->channel, $element, $dataNode );
* Adds the optional feed elements to the XML document being generated.
private function generateOptional()
$elements =
array( 'language', 'copyright', 'author',
'webMaster', 'published', 'updated',
'category', 'generator', 'docs',
'ttl', 'image', 'rating',
'textInput', 'skipHours', 'skipDays',
foreach ( $elements as $element )
$this->generateMetaData( $this->channel, 'lastBuildDate', $data->date->format( 'D, d M Y H:i:s O' ) );
$this->generateMetaData( $this->channel, 'pubDate', $data->date->format( 'D, d M Y H:i:s O' ) );
$this->generateImage( $this->image );
$this->generateSkipHours( $this->skipHours );
$this->generateSkipDays( $this->skipDays );
$this->generateTextInput( $this->textInput );
$this->generateCloud( $this->cloud );
foreach ( $this->category as $category )
$this->generateCategory( $category, $this->channel );
$this->generateGenerator( $data, $this->channel );
foreach ( $this->author as $person )
$this->generatePerson( $person, $this->channel, 'managingEditor' );
foreach ( $this->webMaster as $person )
$this->generatePerson( $person, $this->channel, 'webMaster' );
$this->generateAtomSelfLink( $this->id );
foreach ( $data as $dataNode )
$this->generateMetaData( $this->channel, $element, $dataNode );
* Adds a category node to the XML document being generated.
* @param ezcFeedCategoryElement $category The category feed element
* @param DOMElement $root The XML element where to store the category element
private function generateCategory( ezcFeedCategoryElement $category, DOMElement $root )
$element =
$this->xml->createElement( 'category', $data );
$root->appendChild( $element );
$data =
$category->scheme;
$this->addAttribute( $element, 'domain', $data );
* Adds a person node to the XML document being generated.
* @param ezcFeedPersonElement $person The person feed element
* @param DOMElement $root The XML element where to store the person element
* @param string $elementName The feed element name (eg 'author')
private function generatePerson( ezcFeedPersonElement $person, DOMElement $root, $elementName )
$data =
"{
$email} ({
$name})
";
$element =
$this->xml->createElement( $elementName, $data );
$root->appendChild( $element );
* Adds a generator node to the XML document being generated.
* @param ezcFeedGeneratorElement $generator The generator feed element
* @param DOMElement $root The XML element where to store the generator element
private function generateGenerator( ezcFeedGeneratorElement $generator, DOMElement $root )
$name =
$generator->name;
$version =
$generator->version;
$data =
$data .
" {$version}";
$data =
$data .
" ({$url})";
$element =
$this->xml->createElement( 'generator', $data );
$root->appendChild( $element );
* Adds an image node to the XML document being generated.
* @param ezcFeedImageElement $feedElement The image feed element
private function generateImage( ezcFeedImageElement $feedElement )
$image =
$this->xml->createElement( 'image' );
$this->channel->appendChild( $image );
$elements =
array( 'url', 'title', 'link' );
foreach ( $elements as $element )
$data =
$feedElement->$element;
$this->generateMetaData( $image, $element, $data );
$elements =
array( 'description', 'width', 'height' );
foreach ( $elements as $element )
$data =
$feedElement->$element;
$this->generateMetaData( $image, $element, $data );
* Adds a skipHours node to the XML document being generated.
* @param ezcFeedSkipHoursElement $feedElement The skipHours feed element
private function generateSkipHours( ezcFeedSkipHoursElement $feedElement )
$tag =
$this->xml->createElement( 'skipHours' );
$this->channel->appendChild( $tag );
$data =
$feedElement->hours;
foreach ( $data as $dataNode )
$this->generateMetaData( $tag, 'hour', $dataNode );
* Adds a skipDays node to the XML document being generated.
* @param ezcFeedSkipDaysElement $feedElement The skipDays feed element
private function generateSkipDays( ezcFeedSkipDaysElement $feedElement )
$tag =
$this->xml->createElement( 'skipDays' );
$this->channel->appendChild( $tag );
$data =
$feedElement->days;
foreach ( $data as $dataNode )
$this->generateMetaData( $tag, 'day', $dataNode );
* Adds an textInput node to the XML document being generated.
* @param ezcFeedTextInputElement $feedElement The textInput feed element
private function generateTextInput( ezcFeedTextInputElement $feedElement )
$image =
$this->xml->createElement( 'textInput' );
$this->channel->appendChild( $image );
$elements =
array( 'title', 'description', 'name', 'link' );
foreach ( $elements as $element )
$data =
$feedElement->$element;
$this->generateMetaData( $image, $element, $data );
* Adds a cloud node to the XML document being generated.
* @param ezcFeedCloudElement $feedElement The cloud feed element
private function generateCloud( ezcFeedCloudElement $feedElement )
$elements =
array( 'domain', 'port', 'path', 'registerProcedure', 'protocol' );
foreach ( $elements as $element )
$data =
$feedElement->$element;
$attributes[$element] =
$data;
$this->generateMetaDataWithAttributes( $this->channel, 'cloud', false, $attributes );
* Adds an atom:link node to the XML document being generated, plus the namespace.
* @param ezcFeedIdElement $feedElement The link feed element
private function generateAtomSelfLink( ezcFeedIdElement $feedElement )
$this->addAttribute( $this->root, 'xmlns:atom', ezcFeedAtom::NAMESPACE_URI );
$link =
$this->xml->createElement( 'atom:link' );
$this->channel->appendChild( $link );
$this->addAttribute( $link, 'href', $feedElement->id );
$this->addAttribute( $link, 'rel', 'self' );
$this->addAttribute( $link, 'type', self::CONTENT_TYPE );
* Adds the feed items to the XML document being generated.
private function generateItems()
foreach ( $items as $item )
$itemTag =
$this->xml->createElement( 'item' );
$this->channel->appendChild( $itemTag );
$atLeastOneRequiredFeedItemPresent =
false;
$elements =
array( 'title', 'description' );
foreach ( $elements as $attribute )
$data =
$item->$attribute;
$atLeastOneRequiredFeedItemPresent =
true;
if ( $atLeastOneRequiredFeedItemPresent ===
false )
$requiredElements =
$elements;
for ( $i =
0; $i <
count( $requiredElements ); $i++
)
$requiredElements[$i] =
"/{$this->root->nodeName}/item/{
$requiredElements[$i]}";
$optional =
array( 'title', 'link', 'description',
'author', 'category', 'comments',
'enclosure', 'id', 'published',
foreach ( $optional as $attribute )
$metaData =
$item->$attribute;
$this->generateMetaData( $itemTag, 'comments', $metaData );
if ( isset
( $metaData->isPermaLink ) )
$permaLink =
( $metaData->isPermaLink ===
true ) ?
'true' :
'false';
$attributes =
array( 'isPermaLink' =>
$permaLink );
$this->generateMetaDataWithAttributes( $itemTag, 'guid', $metaData->id, $attributes );
foreach ( $metaData as $dataNode )
$this->generateCategory( $dataNode, $itemTag );
foreach ( $metaData as $person )
$this->generatePerson( $person, $itemTag, 'author' );
$this->generateMetaData( $itemTag, 'pubDate', $metaData->date->format( 'D, d M Y H:i:s O' ) );
foreach ( $metaData as $dataNode )
$elements =
array( 'url', 'length', 'type' );
foreach ( $elements as $key )
if ( isset
( $dataNode->$key ) )
$attributes[$key] =
$dataNode->$key;
$this->generateMetaDataWithAttributes( $itemTag, 'enclosure', false, $attributes );
if ( !isset
( $metaData->url ) )
$attributes =
array( 'url' =>
$metaData->url );
$this->generateMetaDataWithAttributes( $itemTag, 'source', $metaData, $attributes );
$this->addAttribute( $itemTag, 'xml:lang', $metaData );
$this->generateMetaData( $itemTag, $attribute, $metaData );
$this->generateItemModules( $item, $itemTag );
* Parses the provided XML element object and stores it as a feed item in
* the provided ezcFeed object.
* @param ezcFeedElement $element The feed element object that will contain the feed item
* @param DOMElement $xml The XML element object to parse
private function parseItem( ezcFeedElement $element, DOMElement $xml )
foreach ( $xml->childNodes as $itemChild )
if ( $itemChild->nodeType ===
XML_ELEMENT_NODE )
$tagName =
$itemChild->tagName;
$subElement =
$element->add( $tagName );
$subElement->text =
$itemChild->textContent;
$subElement =
$element->add( $tagName );
$subElement->name =
$itemChild->textContent;
// @todo parse textContent if it has the format: email@host (name)
$element->published =
$itemChild->textContent;
$subElement =
$element->add( $tagName );
$attributes =
array( 'url' =>
'url', 'type' =>
'type', 'length' =>
'length' );
foreach ( $attributes as $name =>
$alias )
if ( $itemChild->hasAttribute( $name ) )
$subElement->$alias =
$itemChild->getAttribute( $name );
$subElement =
$element->add( $tagName );
$subElement->href =
$itemChild->textContent;
$subElement =
$element->add( $tagName );
$subElement->source =
$itemChild->textContent;
if ( $itemChild->hasAttribute( 'url' ) )
$subElement->url =
$itemChild->getAttribute( 'url' );
$subElement =
$element->add( $tagName );
$subElement->term =
$itemChild->textContent;
if ( $itemChild->hasAttribute( 'domain' ) )
$subElement->scheme =
$itemChild->getAttribute( 'domain' );
$subElement =
$element->add( 'id' );
$subElement->id =
$itemChild->textContent;
if ( $itemChild->hasAttribute( 'isPermaLink' ) )
$value =
$itemChild->getAttribute( 'isPermaLink' );
$subElement->isPermaLink =
( strtolower( $value ) ===
'true' ) ?
true :
false;
// check if it's part of a known module/namespace
$this->parseModules( $element, $itemChild, $tagName );
if ( $xml->hasAttribute( 'xml:lang' ) )
$element->language =
$xml->getAttribute( 'xml:lang' );
* Parses the provided XML element object and stores it as a feed image in
* the provided ezcFeedImageElement object.
* @param ezcFeedImageElement $element The feed element object that will contain the feed image
* @param DOMElement $xml The XML element object to parse
private function parseImage( ezcFeedImageElement $element, DOMElement $xml )
foreach ( $xml->childNodes as $itemChild )
if ( $itemChild->nodeType ===
XML_ELEMENT_NODE )
$tagName =
$itemChild->tagName;
$element->$tagName =
$itemChild->textContent;
* Parses the provided XML element object and stores it as a feed element
* of type skipHours in the provided ezcFeedSkipHoursElement object.
* @param ezcFeedSkipHoursElement $element The feed element object that will contain skipHours
* @param DOMElement $xml The XML element object to parse
private function parseSkipHours( ezcFeedSkipHoursElement $element, DOMElement $xml )
foreach ( $xml->childNodes as $itemChild )
if ( $itemChild->nodeType ===
XML_ELEMENT_NODE )
$tagName =
$itemChild->tagName;
if ( $tagName ===
'hour' )
$values[] =
$itemChild->textContent;
$element->hours =
$values;
* Parses the provided XML element object and stores it as a feed element
* of type skipDays in the provided ezcFeedSkipDaysElement object.
* @param ezcFeedSkipDaysElement $element The feed element object that will contain skipDays
* @param DOMElement $xml The XML element object to parse
private function parseSkipDays( ezcFeedSkipDaysElement $element, DOMElement $xml )
foreach ( $xml->childNodes as $itemChild )
if ( $itemChild->nodeType ===
XML_ELEMENT_NODE )
$tagName =
$itemChild->tagName;
if ( $tagName ===
'day' )
$values[] =
$itemChild->textContent;
$element->days =
$values;
* Parses the provided XML element object and stores it as a textInput in
* the provided ezcFeedTextInputElement object.
* @param ezcFeedTextInputElement $element The feed element object that will contain the textInput
* @param DOMElement $xml The XML element object to parse
private function parseTextInput( ezcFeedTextInputElement $element, DOMElement $xml )
foreach ( $xml->childNodes as $itemChild )
if ( $itemChild->nodeType ===
XML_ELEMENT_NODE )
$tagName =
$itemChild->tagName;
$element->$tagName =
$itemChild->textContent;