DEV Community

Cover image for eZ Publish's Native RSS Import: Making It Actually Import <enclosure> Media (2012)
Hamdi LAADHARI
Hamdi LAADHARI

Posted on

eZ Publish's Native RSS Import: Making It Actually Import <enclosure> Media (2012)

Archival repost — originally published on my old blog on July 20, 2012. Translated from French, lightly cleaned up for dev.to — I also fixed smart-quote encoding issues throughout the PHP code blocks that would have made them fail to parse. eZ Publish is now Ibexa DXP, but the kernel mechanism described here (and the "quick and dirty vs. extension hook" tradeoff) is unchanged.

eZ Publish lets you import content from an RSS feed into eZ Publish content objects without writing a single line of code. But that native feature doesn't import the media referenced in the <enclosure> tag:

<enclosure url="http://www.example.com/images/voiture.jpg" length="" type="image/jpeg"/>
Enter fullscreen mode Exit fullscreen mode

I'll show you how to fetch that media (image, or any other file like PDF, DOC, or FLV) and insert it transparently into your eZ Publish content. This feature is a bit hardcoded in eZ Publish and isn't cleanly extensible out of the box. I'll show you the quick and dirty way to get there first, then the cleaner way — you decide how much time it's worth spending.

Quick and dirty implementation

Here are the core files affected by our changes:

  • The setObjectAttributeValue() function in cronjobs/rssimport.php (the PHP script called by cron to fetch new items from the RSS feeds configured in the back office)
  • The rssFieldDefinition() method in kernel/classes/ezrssimport.php

setObjectAttributeValue() handles fetching the different attribute types (text line, XML block), so that's naturally where we add handling for the ezimage attribute (this also works with ezfile). We add a case 'ezimage':

function setObjectAttributeValue( $objectAttribute, $value )
{
    //...
    switch( $dataType )
    {
        //...
        case 'ezimage':
        {
            $file = pathinfo($value);
            $image = eZHTTPTool::getDataByURL( $value );
            if ($image !== false)
            {
                $fp = fopen('/tmp/'.$file['basename'], 'wb');
                fwrite($fp, $image, strlen($image));
                fclose($fp);
                $objectAttribute->fromString( '/tmp/'.$file['basename'] );
            }
        } break;
        //...
    }
}
Enter fullscreen mode Exit fullscreen mode

Once eZ Publish knows how to handle ezimage, we need to add Item – Enclosure – Url to the mapping <select>. That's the rssFieldDefinition() method:

case '2.0':
case '0.91':
case '0.92':
{
  return array( 'item' => array( 'elements' => array( 'title',
                                                      'link',
                                                      'description',
                                                      'author',
                                                      'category',
                                                      'comments',
                                                      'guid',
                                                      'pubDate',
                                                      'enclosure' => array( 'attributes' => array( 'url' ) ) ) ),
                'channel' => array( 'elements' => array( 'title',
                                                         'link',
                                                         'description',
                                                         'copyright',
                                                         'managingEditor',
                                                         'webMaster',
                                                         'pubDate',
                                                         'lastBuildDate',
                                                         'category',
                                                         'generator',
                                                         'docs',
                                                         'cloud',
                                                         'ttl' ) ) );
}
Enter fullscreen mode Exit fullscreen mode

Cleaner implementation

Instead of editing the rssimport.php cron script directly, you can copy it into your own extension, make the ezimage changes there, and have that run instead of eZ Publish's default rssimport.php.

rssFieldDefinition() is called from another method in the same class, and there's a hook there that lets you extend the definition from classes living in your custom extensions. Here's the hook, inside fieldMap():

$fieldDefinition = eZRSSImport::rssFieldDefinition();

$ini = eZINI::instance();
foreach( $ini->variable( 'RSSSettings', 'ActiveExtensions' ) as $activeExtension )
{
    if ( file_exists( eZExtension::baseDirectory() . '/' . $activeExtension . '/rss/' . $activeExtension . 'rssimport.php' ) )
    {
        include_once( eZExtension::baseDirectory() . '/' . $activeExtension . '/rss/' . $activeExtension . 'rssimport.php' );
        $fieldDefinition = eZRSSImport::arrayMergeRecursive( $fieldDefinition, call_user_func( array( $activeExtension . 'rssimport', 'rssFieldDefinition' ), array() ) );
    }
}
Enter fullscreen mode Exit fullscreen mode

So all we need is a class in extension/myextension/rss/ezrssimage.php with a method of the same name, rssFieldDefinition():

class ezrssimagerssimport
{
    static function rssFieldDefinition()
    {
        return array( 'item' => array( 'elements' => array( 'enclosure' => array( 'attributes' => array( 'url' ) ) ) ) );
    }
}
Enter fullscreen mode Exit fullscreen mode

And declare that class in myextension/settings/site.ini.append.php:

[RSSSettings]
ActiveExtensions[]=ezrssimage
Enter fullscreen mode Exit fullscreen mode

That's it for this one. If I ever find the time I'll package this as a proper extension and publish it on GitHub (unless someone beats me to it).

Let me know if you spot errors or improvements. The PHP snippets above are also up on this gist.

Top comments (0)