eZ Community » Blogs » Sebastiaan van der Vliet » Importing image objects from a RSS feed

By

Sebastiaan van der Vliet

Importing image objects from a RSS feed

Monday 19 September 2011 10:00:15 pm

  • Currently 3 out of 5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Below is a script to import image objects from a RSS feed, such as a Flickr photo feed. It's not a very complicated script, but it combines a few nice simple tasks:

  • parsing a XML file;
  • retreiving images from another server and storing these locally;
  • creating image objects.

The script could have been even more simple if function eZImageAliasHandler::initializeFromFile would use 

 if ( !@fopen($filename,"r") )

instead of

 if ( !file_exists( $filename ) )

so image files could be retrieved across servers.

You can run this script as follows:
 php extension/[name of your extension]/scripts/importrssimages.php --node=43 --feed="http://api.flickr.com/services/feeds/photos_public.gne?id=11398192@N02&lang=en-us&format=rss_200"

RSS feed used in this example has been selected at random :)

 <?php
//call this script as follows:
//php extension/[name of your extension]/scripts/importrssimages.php --node=43 --feed="http://api.flickr.com/services/feeds/photos_public.gne?id=11398192@N02&lang=en-us&format=rss_200"

set_time_limit ( 0 );
require 'autoload.php';
$cli = eZCLI::instance();
$script = eZScript::instance( array( 'description' => "eZ Publish Flickr import.\n\n",
                                         'use-session' => false,
                                     'use-modules' => true,
                                     'use-extensions' => true,
                         'debug-output' => true,
                    'debug-message' =>true) );

$script->startup();
$options = $script->getOptions( "[feed:][node:]","",
                                array( 'node' => 'parent node_id to upload image object under',
                                       'feed' => 'Flickr feed URL'),
                                false,
                                array( 'user' => true ));

$script->initialize();

//You could put the import user id in a config file
$importUserID = 14;
$user = eZUser::fetch( $importUserID );

$db = eZDB::instance();

if ( !$options['feed'] )
{
    $cli->error( "Specify a Flickr feed URL to import from, e.g.: --feed=\"http://api.flickr.com/services/feeds/photos_public.gne?id=11398192@N02&lang=en-us&format=rss_200\"" );
    $script->shutdown( 1 );
}


if ( $options['node'] )
{
    $folderID = $options['node']; 
    $folderNode = eZContentObjectTreeNode::fetch( $folderID );
    
    if (!$folderNode)
    {
        $cli->error( "Folder with ID ".$folderID." does not exist." );
        $script->shutdown( 1 );
    }
}
else
{
     $cli->error( "Specify a folder NodeID where the image objects should be stored." );
     $script->shutdown( 1 );
}


//Getting the RSS feed from Flickr and parsing the XML.
$xmlObj = simplexml_load_file( $options['feed'] );
if ($xmlObj)
{
    $feed_items=array();
    $i=0;
    foreach ($xmlObj->channel->item as $item)
    {
        $media = $item->children("http://search.yahoo.com/mrss/");
        $feed_items[$i]['title']=(string)$media->title;
        $feed_items[$i]['description']=(string)$media->description;
        $contentAttr = $media->content->attributes();
        $feed_items[$i]['image'] =  (string)$contentAttr['url'];
        $i++;
    }
}
else
{
    $cli->error( "Feed contains no data");
    $script->shutdown();

}

//Looping through all the collected images.
foreach($feed_items as $item)
{
    //strip GET stuff.
    $item['image']=preg_replace('/\\?.*/', '', $item['image']);
    
    if ( $item['image'] )
    {
        //this part is mostly based on http://share.ez.no/learn/ez-publish/creating-ez-publish-objects-in-php/
        $params = array();
        $params['class_identifier'] = 'image';
        $params['creator_id'] = $user->attribute( 'contentobject_id' ); 
        $params['parent_node_id'] = $folderID;        
        
        //things might be better if the function eZImageAliasHandler::initializeFromFile would use
        //if ( !@fopen($f ilename,"r") ) instead of if ( !file_exists( $filename ) ) 
        //so image files could be retrieved across servers. Now we need to store the files locally twice.
        
        $sys = eZSys::instance();
        $storage_dir = $sys->storageDirectory();
        $tempDir = $storage_dir . '/flickrstream/orginal/'.$folderID.'/';
        $imageName = basename( $item['image'] );
        if ( file_exists( $tempDir.$imageName) )
        {
            $cli->notice("Item already exists");
            continue;
        }
    
        if ( @fopen($item['image'],"r") )
        {
            $buf = eZHTTPTool::sendHTTPRequest( $item['image'], 80, false, 'eZ Publish', false );
            $header = false;
            $body = false;
            if ( eZHTTPTool::parseHTTPResponse( $buf, $header, $body ) )
            {
                eZFile::create( $imageName, $tempDir, $body );
            }
            $sourceMimeData = eZMimeType::findByFileContents( $imageName );
        }
        $params ['storage_dir' ] = $tempDir;    
        $item['image'] = $imageName;
        //extra code ends here

        $attributesData = array();
        $attributesData['name'] = $item['title']; 
        $attributesData ['image'] = $sourceMimeData['filename']; 
        
        
        $XMLContent = strip_tags($item['description']);
        $parser = new eZSimplifiedXMLInputParser( false, true, eZXMLInputParser::ERROR_ALL, true );
        $parser->setParseLineBreaks( true );
        $document = $parser->process( $XMLContent );
        $xmlString = eZXMLTextType::domString( $document );
        $attributesData['caption'] = $xmlString;
        
        $params['attributes'] = $attributesData;

        $imageObject = eZContentFunctions::createAndPublishObject( $params );

        if ($imageObject)
        {
            $cli->notice("Created image ".$item['title']);
        }
    }
    
}

$cli->notice("Script is done.");

$script->shutdown();

?>