efeed

Feed Writer Generator Extension (RSS 1.0, RSS 2.0, and ATOM 1.0)
38 followers

Feed Writer Generator Extension to create your feeds. Currently supports RSS 1.0, RSS 2.0 and ATOM 1.0.

IMPORTANT I have updated the github repo so it is now isolated to update independently from other extensions. Get the most up to date version from its github repository.

Requirements

  • Developed using Yii version 1.1.5

Usage

Unzip the contents of the package and place it on your protected/extensions folder.

Examples of use

RSS 1.0

Yii::import('ext.feed.*');
 
// specify feed type
$feed = new EFeed(EFeed::RSS1);
$feed->title = 'Testing the RSS 1 EFeed class';
$feed->link = 'http://www.ramirezcobos.com';
$feed->description = 'This is test of creating a RSS 1.0 feed by Universal Feed Writer';
$feed->RSS1ChannelAbout = 'http://www.ramirezcobos.com/about';
// create our item  
$item = $feed->createNewItem();
$item->title = 'The first feed';
$item->link = 'http://www.yiiframework.com';
$item->date = time();
$item->description = 'Amaz-ii-ng <b>Yii Framework</b>';
$item->addTag('dc:subject', 'Subject Testing');
 
$feed->addItem($item);
 
$feed->generateFeed();

RSS 2.0

Yii::import('ext.feed.*');
// RSS 2.0 is the default type
$feed = new EFeed();
 
$feed->title= 'Testing RSS 2.0 EFeed class';
$feed->description = 'This is test of creating a RSS 2.0 Feed';
 
$feed->setImage('Testing RSS 2.0 EFeed class','http://www.ramirezcobos.com/rss',
'http://www.yiiframework.com/forum/uploads/profile/photo-7106.jpg');
 
$feed->addChannelTag('language', 'en-us');
$feed->addChannelTag('pubDate', date(DATE_RSS, time()));
$feed->addChannelTag('link', 'http://www.ramirezcobos.com/rss' );
 
// * self reference
$feed->addChannelTag('atom:link','http://www.ramirezcobos.com/rss/');
 
$item = $feed->createNewItem();
 
$item->title = "first Feed";
$item->link = "http://www.yahoo.com";
$item->date = time();
$item->description = 'This is test of adding CDATA Encoded description <b>EFeed Extension</b>';
// this is just a test!!
$item->setEncloser('http://www.tester.com', '1283629', 'audio/mpeg');
 
$item->addTag('author', 'thisisnot@myemail.com (Antonio Ramirez)');
$item->addTag('guid', 'http://www.ramirezcobos.com/',array('isPermaLink'=>'true'));
 
$feed->addItem($item);
 
$feed->generateFeed();
Yii::app()->end();

ATOM 1.0

Yii::import('ext.feed.*');
 
 
$feed = new EFeed(EFeed::ATOM);
 
// IMPORTANT : No need to add id for feed or channel. It will be automatically created from link.
$feed->title = 'Testing the ATOM RSS EFeed class';
$feed->link = 'http://www.ramirezcobos.com';
 
$feed->addChannelTag('updated', date(DATE_ATOM, time()));
$feed->addChannelTag('author', array('name'=>'Antonio Ramirez Cobos'));
 
$item = $feed->createNewItem();
 
$item->title = 'The first Feed';
$item->link  = 'http://www.ramirezcobos.com';
// we can also insert well formatted date strings
$item->date ='2010/24/12';
$item->description = 'Test of CDATA Encoded description <b>EFeed Extension</b>';
 
$feed->addItem($item);
 
$feed->generateFeed();

Change Log

  • v.1.3 Added stylesheet support
  • v.1.2 Added support for atom:link
  • v.1.1 Fixed bug on EFeedItemAtom thanks to Flokey82

Resources

2amigOS!
web development has never been so fun
www.2amigos.us - under construction -

Total 20 comments

#13059 report it
BorisK at 2013/04/30 06:03pm
Re: Namespace prefix atom on link is not defined

@Brian Nettles

Namespace prefix atom on link is not defined
I am using feed.v1.3.zip with the latest YII release as of about 3 months ago.

You can downgrade the extension to the version 1.2 without this bug

#12312 report it
Jmper at 2013/03/13 07:39am
Secure feeds

I faced the problem with secure feeds (using https). The error during feed generation was "{link} does not seem to be a valid URL".

It turned out the regex used to validate url didn't take into account https (class EFeedItemAbstract, function setLink, line 110):

$validator->pattern = '/(((f|ht){1}tp:\/\/)[-a-zA-Z0-9@:%_\+.~#?&\/\/=]+)/i';

I fixed it by modifying this line as follows:

$validator->pattern = '/(((f|ht){1}tps?:\/\/)[-a-zA-Z0-9@:%_\+.~#?&\/\/=]+)/i';
#12073 report it
Antonio Ramirez at 2013/02/26 05:48am
@Stratigos

You are right,

Would be nice to have some proposals at github

#11944 report it
Stratigos at 2013/02/14 12:20pm
sidestepped...

@Antonio

That doesnt answer the question. The issue is that there isnt a way to have multiple tags of the same name as children of some parent tag/element (or actually, multiple tags of the same name at all).

For example, Im unable to do this:

<media:group><media:content/><media:content/><media:content/></media:group>

Or this:

<item>...<media:content/><media:content/><media:content/></item>

So im basically putting this out there for anyone in the same position - if you need to publish to a partner with specific needs that require multiple elements of the same name per item element, EFeed wont work, and I havent arrived at an elegant way to extend EFeed to get around it (issue is up in Yii framework classes employed).

#11824 report it
Brian Nettles at 2013/02/06 07:34am
Namespace prefix atom on link is not defined

I get an error using chrome due to this line.

$feed->addChannelTag('atom:link','http://estorefeedback.com/rss/'.$url_rewrite );

Namespace prefix atom on link is not defined

I am using feed.v1.3.zip with the latest YII release as of about 3 months ago.

Any thoughts?

#10599 report it
Antonio Ramirez at 2012/11/06 02:33pm
@Stratigos

Seems that EFeed needs refactoring, I didn't include attributes for the heads of the media type required:

// Example rss 2 header
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">

As you can see on https://github.com/tonydspaniard/Yii-extensions/blob/master/extensions/EFeed/EFeed.php#L310 the extension doesn't support that yet. But it won't be too hard to add that ability to provide media types for the feed.

Hope I have time soon to do it.


About your second limitation:

Arrays are not supported on the 'content', you could just create the tags and pass them through:

$innerTag = CHtml::tag('media:description',array('attribute1a' => 'value1a'));
 
$item->addTag('media:content', $innerTag, array(
    'attribute1' => 'value1',
    'attribute2' => 'value2',
));
#10598 report it
Antonio Ramirez at 2012/11/06 02:23pm
@Stratigos

Big apologies for the time not answering the requests. Nowadays, I am truly, very busy and unable to support as much as I would love to, to all extensions that I have created.

That is the reason why I published all my extensions to GitHub so to be able to collaborate with all of you and make them better whilst at the same being able to continue with my work-responsibilities.

Nevertheless, I made a mistake by publishing all my work in one piece, so I am willing to publish them one by one to a single repository respectively.

Would be great that if any of you have suggestions, issues and or improvements to add to it, could help me at github...

I will try to get back asap, but I am too busy, seriously.

Thanks for your understanding...

#10595 report it
Stratigos at 2012/11/06 12:23pm
Another limitation?

In addition to my previous question which has not been answered since July, I have another question which may be a limitation of EFeed.

Im trying to create a child node of an existing item node. Id like for it to have its own text node, as well as attributes. I dont seem to have this option with EFeed, or perhaps I am using it wrong.

Id like a structure as follows:

<item>
    ...other nodes...
    <media:content attribute1='value1' attribute2='value2'>
        <media:description attribute1a='value1a'>DESCRIPTION TEXT</media:description>
    </media:content>
</item>

If I create this via:

$innerTags = array(
    'media:description' => array('attribute1a' => 'value1a');
);
$item->addTag('media:content', $innerTags, array(
    'attribute1' => 'value1',
    'attribute2' => 'value2',
));

I cant seem to add any content to the %media:description% tag, no matter how I manipulate how that variable is assigned (arrays within arrays, explicitly naming an array cell 'content', appending an array to the array passed into the addTag() call...), I am unable to make it a non-self closing tag with some text in its text node. Ive tried creating a new EFeedTag object, which results in object-convert-to-string exceptions.

Am I doing something wrong? How can I make a non self-closing tag with attributes a child of an existing non self-closing tag?

All in all I think PHP's DOMDocument class is a much more reliable means of creating feeds than EFeed for these reasons. Can we expect an update, or at least a logical response, anytime soon?

#9069 report it
Leffe at 2012/07/17 03:26pm
Thanks

While I don't have an answer for Stratigos question, it made me realize that I should spend a few words and send my thanks for this extension.

I'm just a random individual who have set up a Yii site, but just as I like to get feedback on free work, I'm sure you like that too. So thanks for the extension which for me have worked very well.

#9068 report it
Stratigos at 2012/07/17 02:49pm
Re: Multiple media:thumbnail tags

Thanks for responding, but would you care to elaborate? The Yahoo mRSS standard states that it is perfectly valid to use multiple %media:thumbnail% tags per item. Im wondering why this extension overlooks this issue.

#9066 report it
mnogokotin at 2012/07/17 02:08pm
thank you

but cannot add image and ico to feed

#9064 report it
Stratigos at 2012/07/17 02:00pm
Multiple media:thumbnail tags

Hello,

EFeed is a nice extension which allows a simple interface for producing an RSS or mRSS feed. Its worked well for my company's app thus far. Thanks for providing EFeed to the Yii community.

Recently, we've decided we want to include the full inventory of thumbnails for an image gallery for a single item. I need to include multiple %media:thumbnail url=''% tags. I seem to be unable to do this, as the inherited functionality for EFeedItemAbstract::addTag() effectively overwrites any existing tag.

I am aware that alternatively, I can create a separate images feed which contains one item per media:content, to use to render a feed of all images. This is not an ideal setup for our syndication.

Is there a way I can add multiple %media:thumbnail% tags to an item with the latest version of EFeed?

Thanks!

#7178 report it
Antonio Ramirez at 2012/03/01 06:40am
@chuvbiz

I'll do it on my free time, thanks for pointing that out, but there are ways to tell people what to do or not, don't you think?

Moreover, there is a GitHub project where YOU can support the extension and help the community with the change.

#7177 report it
chuvbiz at 2012/03/01 06:23am
RSS1: tag CHANNEL must be open
$feed = new EFeed(EFeed::RSS1);
foreach ($news as $news_item) {
    $item = $feed->createNewItem();
    $item->title = $news_item->title;
    ...                      
    $feed->addItem($item);
}
$feed->generateFeed();

This code generate next:

<rdf:RDF xmlns:rdf="" xmlns="" xmlns:dc="">
<channel rdf:about=""/>
<title></title>
<link></link>
<description>
</description>
<ChannelAbout></ChannelAbout>
<items> ...

Why tag channel rdf:about=""/> is closed? "/>" Fix this bug!

#7053 report it
DarkNSF at 2012/02/21 01:38pm
Great extension, only one suggestion

Having a return rss content option would be nice. Like this:

This is useful for those who may want to cache

/**
     * 
     * Generates the Feed
     */
    public function generateFeed($return=false)
  {
    if (!$return)
    {
          header("Content-type: text/xml");
    }
 
        $returnString = $this->renderHead($return);
        $returnString .= $this->renderChannels($return);
        $returnString .= $this->renderItems($return);
        $returnString .= $this->renderBottom($return);
 
    if ($return)
    {
      return $returnString;
    }
    }
    /**
     * 
     * Prints the xml and rss namespace
     * 
     */
    private function renderHead($return=false)
    {
        $content  = '<?xml version="1.0" encoding="utf-8"?>' . PHP_EOL;
        if(!empty($this->stylesheets))
            $content .= implode (PHP_EOL, $this->stylesheets);
 
        if($this->type == self::RSS2)
        {
            $content .= CHtml::openTag('rss',array(
                        "version"=>"2.0",
                        "xmlns:content"=>"http://purl.org/rss/1.0/modules/content/",
                        "xmlns:wfw"=>"http://wellformedweb.org/CommentAPI/")).PHP_EOL;  
        }    
        elseif($this->type == self::RSS1)
        {
            $content .= CHtml::openTag('rdf:RDF',array(
                        "xmlns:rdf"=>"http://www.w3.org/1999/02/22-rdf-syntax-ns#",
                        "xmlns"=>"http://purl.org/rss/1.0/",
                        "xmlns:dc"=>"http://purl.org/dc/elements/1.1/"
                    )).PHP_EOL;
        }
        else if($this->type == self::ATOM)
        {
            $content .= CHtml::openTag('feed', array("xmlns"=>"http://www.w3.org/2005/Atom")).PHP_EOL;
        }
 
    if ($return)
    {
      return $content;
    }
    else
    {
      echo $content;
    }
    }
    /**
     * 
     * Prints the xml closing tags
     * 
     */
    private function renderBottom($return=false)
    {
    $content = '';
 
        if($this->type == self::RSS2)
        {
            $content .= CHtml::closeTag('channel');
            $content .= CHtml::closeTag('rss');
        }    
        elseif($this->type == self::RSS1)
        {
            $content .= CHtml::closeTag('rdf:RDF');
        }
        else if($this->type == self::ATOM)
        {
            $content .= CHtml::closeTag('feed');                
        }
 
    if ($return)
    {
      return $content;
    }
    else
    {
      echo $content;
    }
    }
    /**
     * 
     * Prints the channels of the xml document
     * @throws CException
     */
    private function renderChannels($return=false)
  {
    $content = '';
 
        switch ($this->type) 
        {
           case self::RSS2: 
                $content .= '<channel>' . PHP_EOL;        
                break;
           case self::RSS1: 
                if(null !== $this->RSS1ChannelAbout )
                    $content .= CHtml::tag('channel',array('rdf:about'=>$this->RSS1ChannelAbout ));
                else 
                    $content .= CHtml::tag('channel',array('rdf:about'=>$this->link));
                break;
        }
 
        // Printing channel items
        foreach ($this->feedElements->itemAt('channels') as $key => $value) 
        {
            if($this->type == self::ATOM && $key == 'link') 
            {
                // ATOM prints link element as href attribute
                $content .= $this->makeNode($key,'',array('href'=>$value));
                // And add the id for ATOM
                $content .= $this->makeNode('id',$this->uuid($value,'urn:uuid:'));
            }
            else
            {
                $content .= $this->makeNode($key, $value);
            }    
 
        }
 
        // RSS 1.0 have special tag <rdf:Seq> with channel 
        if($this->type == self::RSS1)
        {
            if( null === $this->feedElements->itemAt('items') )
                throw new CException( Yii::t('EFeed', 'No items have been set') );
 
            $content .= "<items>" . PHP_EOL . "<rdf:Seq>" . PHP_EOL;
 
            foreach ($this->feedElements->itemAt('items') as $item) 
            {
                $tag = $item->link;
 
                if(null === $tag )
                    throw new CException( Yii::t('EFeed', 'For RSS 1.0 specifications link element should be add per item') );
 
                $content .= CHtml::tag('rdf:li',array('resource'=>$tag->content ),true).PHP_EOL;
            }
            $content .= "</rdf:Seq>" . PHP_EOL . "</items>" . PHP_EOL;
        }
 
    if ($return)
    {
      return $content;
    }
    else
    {
      echo $content;
    }
    }
    /**
     * 
     * Prints feed items
     * @throws CException
     */
    private function renderItems($return=false)
    {    
        if(null === $this->feedElements->itemAt('items'))
            throw new CException( Yii::t('EFeed', 'No feed items configured') );
 
    $content = '';
        foreach ($this->feedElements->itemAt('items') as $item)
            $content .= $item->getNode();
 
    if ($return)
    {
      return $content;
    }
    else
    {
      echo $content;
    }
    }
#4009 report it
Antonio Ramirez at 2011/05/27 02:21am
@cstdenis

Great suggestion!

I am in the middle of adding MRSS and iTunes support to the extension. Unfortunately I am very busy at the moment.

I will consider the dataProvider recommendation aswel. Very good feedback, thanks.

#3899 report it
Cstdenis at 2011/05/18 08:50pm
Nice, class but could use some improvments.

I need MRSS (Media RSS) support so I tried to extend your class to add the necessary second xmlns, but I found $type and renderHead() private rather than protected preventing this.

You should change your private classes, when appropriate, protected to make it more extensible.

Even better, for my particular needs, would have been for renderHead() to either get the header from the appropriate EFeedItem class (not sure how you would structure that well) or to build it's data from a modifiable associative array.

I would also be nice to have it behave like classes such as CGridView where a dataProvider can be passed to it along with a list of column names and the items auto populated from that.

#3022 report it
Dana at 2011/03/08 10:17am
Love It

This extension was very easy to get running, and quite effective. Thank you for sharing it.

#2895 report it
emilevdh at 2011/02/23 06:31am
ITunes

@tonydspaniard: Thanks! Looks like an awesome extension.

Please keep us posted with your progress with making your extension more universal.

We will need to use itunes specific tags.

#2631 report it
Antonio Ramirez at 2011/01/24 07:09am
@Sarke & @gusnips

Any feedback to create a better extension always welcome. I would love to make this RSS feed much more universal (iTunes for example?)

Leave a comment

Please to leave your comment.

Create extension