<?php
//VERSION 1.5

/*    <!--/Creative Commons License-->
    <!-- <rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
        <Work rdf:about="">
            <license rdf:resource="http://creativecommons.org/licenses/by/2.5/" />
    <dc:title>makeSSPxml</dc:title>
    <dc:date>2006</dc:date>
    <dc:description>A PHP class designed to take data from Flickr as well as from SSP xml files and dynamically produce a SSP xml file.</dc:description>
    <dc:creator><Agent><dc:title>Rory Jaffe</dc:title></Agent></dc:creator>
    <dc:rights><Agent><dc:title>Rory Jaffe</dc:title></Agent></dc:rights>
    <dc:type rdf:resource="http://purl.org/dc/dcmitype/Text" />
    <dc:source rdf:resource="http://thejaffes.org/" />
        </Work>
        <License rdf:about="http://creativecommons.org/licenses/by/2.5/"><permits rdf:resource="http://web.resource.org/cc/Reproduction"/><permits rdf:resource="http://web.resource.org/cc/Distribution"/><requires rdf:resource="http://web.resource.org/cc/Notice"/><requires rdf:resource="http://web.resource.org/cc/Attribution"/><permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/></License></rdf:RDF> --> */

class makeSSPxml {

//replace following string with your key. This is the only change needed to this file
const APIkey '&api_key=PUT YOUR KEY HERE' # refer as self::APIkey
const RESTreq 'http://www.flickr.com/services/rest/?method=' # self::RESTreq

//internal variables
protected $xmlLocation$refreshNeeded$fileLife;
protected 
$useCaption=true$useThumb=true$useLink=true$isDebug=false$haltOnError=true$useAlbumThumb=true ;
protected 
$albumThumb ;
protected 
$xmlOutput="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<gallery>\n";
protected 
$numImages=100;
protected 
$searchParms ;

protected function 
My_simplexml_load_file($URL//this is needed if file access is disabled in your server configuration
  
{
  
$ch curl_init($URL);

  
curl_setopt($chCURLOPT_RETURNTRANSFER1);
  
curl_setopt($chCURLOPT_HEADER0);

  
$xml simplexml_load_string(curl_exec($ch));

  
curl_close($ch);

  return 
$xml;
}


//constructor
public function __construct($relpath$lifetime) {
    
//requires PHP 5.0 or greater
    
if (version_compare(PHP_VERSION,'5.0.0','<')) {
        die(
'Requires PHP 5.0.0 or greater') ;
    }
    
$this->xmlLocation $relpath ;
    if (
file_exists($this->xmlLocation)) {
        
$this->fileLife filemtime($this->xmlLocation)+$lifetime-time() ;
        if (
$this->fileLife <= 0) {
            
$this->fileLife $lifetime ;
            
$this->refreshNeeded true ;
        } else {
            
$this->refreshNeeded false ;
        }
    } else {
        
$this->fileLife $lifetime ;
        
$this->refreshNeeded true ;
    }
}

//turn on/off optional features (can save xml file size this way)
public function thumbs($yesorno) { $this->useThumb $yesorno ; }
public function 
links($yesorno) { $this->useLink $yesorno ; }
public function 
captions($yesorno) { $this->useCaption $yesorno ; }
public function 
debug($yesorno) { $this->isDebug $yesorno ; }
public function 
number($count) { $this->numImages min($count,500) ; }
public function 
stop_if_error($yesorno) { $this->haltOnError $yesorno ; }
public function 
album_thumbs($yesorno) {$this->useAlbumThumb $yesorno ; }
public function 
set_thumb($url) {$this->albumThumb $url ;}

//converts the Flickr xml to SSP xml
protected function make_album($photos,$title,$desc,$albthumb) {
    
$title htmlspecialchars($title) ;
    
$desc htmlspecialchars($desc) ;
    
$thumb =  ($this->useAlbumThumb && !empty($albthumb)) ? "tn=\"$albthumb\" " '' ;
    
$album "\t<album title=\"$title\" description=\"$desc\" lgpath=\"http://static.flickr.com/\" $thumb>\n" 
    foreach (
$photos as $single) { 
        
$mainurl $single['server'].'/'.$single['id'].'_'.$single['secret'] ;
        
$album .= "\t\t<img src=\"".$mainurl.'.jpg"' ;
        if (
$this->useThumb$album .= ' tn="http://static.flickr.com/'.$mainurl.'_s.jpg"' ;
        if (
$this->useLink$album .= ' link="http://static.flickr.com/'.$mainurl.'_b.jpg"' ;
        if (
$this->useCaption) {
            
$caption htmlspecialchars($single['title']) ;
            
$album .=  ' caption="'.$caption.'"' 
        }
        
$album .= " />\n" ;
    } 
    
$album .= "\t</album>\n" 
    return 
$album ;
}

//use following if want page to expire when cached xml file expires
public function emit_headers() {
    
header('Cache-Control: max-age='.$this->fileLife.', must-revalidate');
    
header('Expires: '.gmdate('D, d M Y H:i:s'time() + $this->fileLife).' GMT'); #date format string constant DATE_RFC1123 in PHP 5.1.1 and later
}

//called at end to save xml file
public function finish() {
    if (!
$this->refreshNeeded) return;
    
$this->xmlOutput .= '</gallery>' ;
    
$tmpname tempnam(dirname($this->xmlLocation),'sspclass'); //just to be safe, will put it in final destination directory
    
file_put_contents($tmpname,$this->xmlOutput) ;
    
chmod($tmpname,0644) ;//tmpfile was 0600, won't display on web page
    
if (!rename($tmpname,$this->xmlLocation)) { //atomic operation, avoid race conditions, but may fail on WinXP server
        
copy($tmpname,$this->xmlLocation) ;//may be forced to do this on WinXP machine, not atomic
        
unlink($tmpname) ; //remove temp even if copy fails
    
}
}

//makes an album out of a particular user's favorites
public function add_favorites($user,$title='',$desc='') {
    if (!
$this->refreshNeeded) return;
    if (
$title=='' || $desc=='' || ($this->useAlbumThumb && empty($this->albumThumb))) {
        
$xml $this->My_simplexml_load_file(self::RESTreq.'flickr.people.getInfo'.self::APIkey.'&user_id='.$user) ;
        if (
$xml!==false && (count($xml->xpath('./err')))==0) {
            if (
$title==''$title $xml->person->username ;
            if (
$desc==''$desc $xml->person->realname .', from '$xml->person->location ;
            if (
$this->useAlbumThumb && empty($this->albumThumb)) $this->albumThumb = (empty($xml->person['iconserver'])) ? 'http://www.flickr.com/images/buddyicon.jpg' "http://static.flickr.com/{$xml->person[iconserver]}/buddyicons/$user.jpg" ;
        } else {
            
$this->error_handler($xml,__METHOD__.'(getInfo)') ;
        }
    }
    
$xml $this->My_simplexml_load_file(self::RESTreq.'flickr.favorites.getPublicList'.self::APIkey.'&user_id='.$user.'&per_page='.$this->numImages) ;
    if (
$xml!==false && (count($xml->xpath('./err')))==0) {
        
$this->xmlOutput .= $this->make_album($xml->photos->photo,$title,$desc,$this->albumThumb) ;
    } else {
        
$this->error_handler($xml,__METHOD__.'(getPublicList)') ;
    }
    
$this->reset() ;
}

//adds interesting photos
public function add_interesting($title='Flickr interestingness photos',$desc='Most interesting photos from today') {
    if (!
$this->refreshNeeded) return;
    
$search = (empty($this->searchParms)) ? '' : ('&'.http_build_query($this->searchParms)) ;
    if (
$desc=='Most interesting photos from today' && !empty($this->searchParms['date'])) {
        
$desc 'Most interesting photos from '.$this->searchParms['date'] ;
    }
    
$xml $this->My_simplexml_load_file(self::RESTreq.'flickr.interestingness.getList'.self::APIkey.'&per_page='.$this->numImages.$search) ;
    if (
$xml!==false && (count($xml->xpath('./err')))==0) {
        
$this->xmlOutput .= $this->make_album($xml->photos->photo,$title,$desc,$this->albumThumb) ;
    } else {
        
$this->error_handler($xml,__METHOD__) ;
    }
    
$this->reset() ;
}

public function 
add_photoset($setno) {
    if (!
$this->refreshNeeded) return;
    
$xml $this->My_simplexml_load_file(self::RESTreq.'flickr.photosets.getInfo'.self::APIkey.'&photoset_id='.$setno) ;
    if (
$xml!==false && (count($xml->xpath('./err')))==0) {
        
$title $xml->photoset->title ;
        
$desc $xml->photoset->description ;
        
$numphotos $xml->photoset['photos'] ;
        
$xml $this->My_simplexml_load_file(self::RESTreq.'flickr.photosets.getPhotos'.self::APIkey.'&photoset_id='.$setno) ; //cannot specify number images in photosets
        
if ($xml!==false && (count($xml->xpath('./err')))==0)  {
            if (
$this->useAlbumThumb && empty($this->albumThumb)) {
                
$selected $xml->xpath('//photo[@isprimary="1"]');
                if (!empty(
$selected[0])) {
                    
$single $selected[0];
                    
$this->albumThumb 'http://static.flickr.com/'.$single['server'].'/'.$single['id'].'_'.$single['secret'].'_s.jpg' ;
                } 
//end if selected
            
//end if useAlbumThumb
            
if ($numphotos $this->numImages) {//need to cut down size of set
                
$i ;
                foreach (
$xml->photoset->photo as $individual) {
                    
$limited_set[] = $individual ;
                    if (++
$i $this->numImages) break ;
                }
                
$this->xmlOutput .= $this->make_album($limited_set,$title,$desc,$this->albumThumb);
            } else { 
//don't need to reduce set size
                
$this->xmlOutput .= $this->make_album($xml->photoset->photo,$title,$desc,$this->albumThumb);
            }
        } else {
            
$this->error_handler($xml,__METHOD__.'(getPhotos)') ;
        }
    } else {
            
$this->error_handler($xml,__METHOD__.'(getInfo)') ;
    }
    
$this->reset() ;
}

public function 
add_pool($pool,$title='',$desc='') {
    if (!
$this->refreshNeeded) return;
    if (
$title=='' || $desc=='') {
        
$xml $this->My_simplexml_load_file(self::RESTreq.'flickr.groups.getInfo'.self::APIkey.'&group_id='.$pool) ;
        if (
$xml!==false && (count($xml->xpath('./err')))==0) {
            if (
$title==''$title $xml->group->name ;
            if (
$desc==''$desc $xml->group->description ;
        } else {
            
$this->error_handler($xml,__METHOD__.'(getInfo)') ;
        }
    }
    if (
$this->useAlbumThumb && empty($this->albumThumb)) {
        
$xml $this->My_simplexml_load_file('http://www.flickr.com/groups_feed.gne?id=' $pool .'&format=rss_200' ) ;
        
$this->albumThumb strtok($xml->channel->image->url,'?') ;
    }
    
$search = (empty($this->searchParms)) ? '' : ('&'.http_build_query($this->searchParms)) ;
    
$xml $this->My_simplexml_load_file(self::RESTreq.'flickr.groups.pools.getPhotos'.self::APIkey.'&group_id='.$pool.'&per_page='.$this->numImages.$search) ;
    if (
$xml!==false && (count($xml->xpath('./err')))==0) {
        
$this->xmlOutput .= $this->make_album($xml->photos->photo,$title,$desc,$this->albumThumb) ;
    } else {
        
$this->error_handler($xml,__METHOD__.'(getPhotos)') ;
    }
    
$this->reset() ;
}

public function 
add_search($title='',$desc='') {
    if (!
$this->refreshNeeded) return;
    
$xml $this->My_simplexml_load_file(self::RESTreq.'flickr.photos.search'.self::APIkey.'&'.http_build_query($this->searchParms).'&per_page='.$this->numImages) ;
    if (
$xml!==false && (count($xml->xpath('./err')))==0) {
        
$this->xmlOutput .= $this->make_album($xml->photos->photo,$title,$desc,$this->albumThumb) ;
    } else {
        
$this->error_handler($xml,__METHOD__) ;
    }
    
$this->reset() ;
}

public function 
add_tags($tags,$title='',$desc='',$tagmode='all') {
    if (!
$this->refreshNeeded) return;
    
$xml $this->My_simplexml_load_file(self::RESTreq.'flickr.photos.search'.self::APIkey.'&tags='.$tags.'&tag_mode='.$tagmode.'&per_page='.$this->numImages.'&'.http_build_query($this->searchParms)) ;
    if (
$xml!==false && (count($xml->xpath('./err')))==0) {
        
$this->xmlOutput .= $this->make_album($xml->photos->photo,$title,$desc,$this->albumThumb) ;
    } else {
        
$this->error_handler($xml,__METHOD__) ;
    }
    
$this->reset() ;
}


public function 
add_xml($relpath) {
    if (!
$this->refreshNeeded) return;
    
$xml $this->My_simplexml_load_file($relpath) ;
    if (
$xml !== false) {
        
$albums $xml->xpath('//album') ;
        if (
count($albums)!=0) {
            foreach (
$albums as $one) {
                
$this->xmlOutput .= $one->asXML() ;
            }
        }
    } else {
        
$this->error_handler($xml,__METHOD__) ;
    }
    
$this->reset() ;
}

//function to dump debug information, abort making xml file
protected function error_handler($xml,$funcname) {
    if (
$this->haltOnError) { 
        
$this->refreshNeeded false 
        
$this->fileLife 60 ;
    }
    if (
$this->isDebug) {
        if (
$xml===false) {
            echo 
"<p>Empty xml fetch in $funcname.</p>" ;
        } else {
            echo 
"<p>Error returned from xml request in $funcname — Error #{$xml->err[code]}, &#8220;{$xml->err[msg]}&#8221;</p>" ;
        }
    }
}

public function 
search_parameter($name,$value) {
    
$this->searchParms[$name] = $value ;
}

public function 
group_thumb($nsid) {
    
$xml $this->My_simplexml_load_file('http://www.flickr.com/groups_feed.gne?id='.$nsid.'&format=rss_200' ) ;
    return 
strtok($xml->channel->image->url,'?') ;
}

public function 
indiv_thumb($nsid) {
    
$xml $this->My_simplexml_load_file(self::RESTreq.'flickr.people.getInfo'.self::APIkey.'&user_id='.$nsid) ;
    
$icons $xml->person['iconserver'] ;
    return (empty(
$icons)) ? 'http://www.flickr.com/images/buddyicon.jpg' 
    
"http://static.flickr.com/$icons/buddyicons/$nsid.jpg" ;
}

protected function 
reset() {
    unset(
$this->searchParms) ;
    unset(
$this->albumThumb) ;
}

//The __toString method will only be called when it is directly combined with echo() or print(). Do not use (string) cast. 
public function __toString() {
    return 
$this->xmlOutput ;
}

}
//end class makeSSPxml
?>