<?php
/**
 * Gamertag class gets gamertag info from Duncan Mackensie's webservice
 *
 * Thanks go to Duncan for the service as it is brilliant and no other such 
 * service exists.
 * 
 * http://duncanmackenzie.net/blog/put-up-a-rest-api-for-xbox-gamertag-data/default.aspx
 *
 * Also, if you build anything that uses this class that may gain any serious 
 * traffic please notify Duncan as he has requested at:
 *
 * http://duncanmackenzie.net/Blog/using-my-xbox-live-data-service
 *
 */
class Gamertag {
    
/**
     * Webservice base url
     */
    
protected $webservice 'http://xboxapi.duncanmackenzie.net/gamertag.ashx?GamerTag=%GAMERTAG%';
    
    
/**
     * The gamerdata, populated as needed
     */
    
private $gamerdata = array(
        
'Gamertag' => ''    
    
);
    
    
/**
     * The resulting XML from the webservice.
     */
    
private $feed null;
    
    
/**
     * Whether the feed has been parsed yet.
     */
    
private $feed_parsed false;
    
/**
     * When the feed was retrieved. 
     * This allows sane serialisation and logic about whether to refresh the 
     * feed or simply use a cached version
     */
    
private $feed_retrieved false;
    
    
/**
     * Constructor requires the gamertag.
     * NB. no validation is done at this stage.
     */
    
public function __construct($gamertag){
        
$this->gamerdata['Gamertag'] = $gamertag;
    }
    
    
    
/**
     * the __sleep function defines what data to save in serialisation
     * @todo I can't remember what this is supposed to return...
     */
    
public function __sleep(){
        return array();
    }
    
    
/**
     * How to wake up the object after serialisation.
     */
    
public function __wakeup(){
    
    }
    
    
/**
     * toString simply returns the gamertag
     */
    
public function __toString(){
        return 
$this->gamerdata['Gamertag'];
    }
    
    
/**
     * Retrieves the XML from a webservice.
     */
    
public function getXML(){
        
$url str_replace'%GAMERTAG%'urlencode($this->gamerdata['Gamertag']), $this->webservice);
        
$xml file_get_contents($url);
        return 
$xml;
    }
    
    
/**
     * Retrieves an element from the feed, or a string snippet.
     */
    
public function retrieve$element$string null$multiple false ){
        if( 
is_null($string) ){
            
$string $this->feed;
        }
        if( 
false === $string ){
            return 
$multiple ? array() : '';
        }
        
$element preg_quote($element'#');
        
$regex '#<'.$element.'>(.*?)</'.$element.'>#s';
        if( !
$multiple){
            
preg_match($regex$string$match);
            return !
is_null($match[1]) ? $match[1] : "";
        }else{
            
preg_match_all($regex$string$matchPREG_PATTERN_ORDER);
            
//print_r(compact('regex','match','string'));
            
return $match[1] ;
        }
    }
    
    
/**
     * This is an XML parser that ignores attributes.
     * We don't need them. If we do later, then I will change the function.
     */
    
public function parseXML(){
        
$this->feed $this->getXML();
        
$this->feed_retrieved time();
        
//reset current array
        
$this->gamerdata = array();
        
        
//get basic info
    
$this->gamerdata['Gamertag'] = $this->retrieve('Gamertag');
        
$this->gamerdata['AccountStatus'] = $this->retrieve('AccountStatus');
        
$this->gamerdata['State'] = $this->retrieve('State');
        
$this->gamerdata['ProfileUrl'] = $this->retrieve('ProfileUrl');
        
$this->gamerdata['TileUrl'] = $this->retrieve('TileUrl');
    
$this->gamerdata['AvatarFullUrl'] = 'http://avatar.xboxlive.com/avatar/'.rawurlencode($this->gamerdata['Gamertag']).'/avatar-body.png';
        
$this->gamerdata['Country'] = $this->retrieve('Country');
        
$this->gamerdata['Location'] = $this->retrieve('Location');
        
$this->gamerdata['Bio'] = $this->retrieve('Bio');
        
$this->gamerdata['Reputation'] = $this->retrieve('Reputation');
        
$this->gamerdata['ReputationImageUrl'] = $this->retrieve('ReputationImageUrl');
        
$this->gamerdata['Zone'] = $this->retrieve('Zone');
        
$this->gamerdata['GamerScore'] = $this->retrieve('GamerScore');
        
        
//get presence info
        
$PresenceInfo $this->retrieve('PresenceInfo');
        
$this->gamerdata['PresenceInfo']['Valid'] = $this->retrieve('Valid'$PresenceInfo);
        
$this->gamerdata['PresenceInfo']['Info'] = $this->retrieve('Info'$PresenceInfo);
        
$this->gamerdata['PresenceInfo']['Info2'] = $this->retrieve('Info2'$PresenceInfo);
        
$this->gamerdata['PresenceInfo']['LastSeen'] = $this->dateFix$this->retrieve('LastSeen'$PresenceInfo) );
        
$this->gamerdata['PresenceInfo']['Online'] = $this->retrieve('Online'$PreseceInfo);
        
$this->gamerdata['PresenceInfo']['StatusText'] = $this->retrieve('StatusText'$PresenceInfo);
        
$this->gamerdata['PresenceInfo']['Title'] = $this->retrieve('Title'$PresenceInfo);
        
        
//get recent games info
        
$Games $this->retrieve('XboxUserGameInfo'nulltrue);
        
$this->gamerdata['RecentGames'] = array();
        foreach(
$Games as $i => $game){
            
$this->gamerdata['RecentGames'][$i]['Name'] = $this->retrieve('Name'$game);
            
$this->gamerdata['RecentGames'][$i]['TotalAchievements'] = $this->retrieve('TotalAchievements'$game);
            
$this->gamerdata['RecentGames'][$i]['TotalGamerScore'] = $this->retrieve('TotalGamerScore'$game);
            
$this->gamerdata['RecentGames'][$i]['Image32Url'] = $this->retrieve('Image32Url'$game);
            
$this->gamerdata['RecentGames'][$i]['Image64Url'] = $this->retrieve('Image64Url'$game);
            
$this->gamerdata['RecentGames'][$i]['LastPlayed'] = $this->dateFix$this->retrieve('LastPlayed'$game) );
            
$this->gamerdata['RecentGames'][$i]['Achievements'] = $this->retrieve('Achievements'$game);
            
$this->gamerdata['RecentGames'][$i]['GamerScore'] = $this->retrieve('GamerScore'$game);
            
$this->gamerdata['RecentGames'][$i]['DetailsURL'] = $this->retrieve('DetailsURL'$game);
        }
        
$this->feed_parsed true;
    }
    
    public function 
dateFix($date_string){
        return 
date('r',strtotime($date_string));
    }
    
    public function 
getString(){
        if(!
$this->feed_parsed){
            
$this->parseXML();
        }
        return 
print_r($this->gamerdatatrue);
    }
    
    public function 
getFeed(){
        if(!
$this->feed_parsed){
            
$this->parseXML();
        }
        return 
$this->feed;
    }
    
    public function 
getArray(){
        if(!
$this->feed_parsed){
            
$this->parseXML();
        }
        return 
$this->gamerdata;
    }
    
    public function 
getJSON(){
        if(!
$this->feed_parsed){
            
$this->parseXML();
        }
        if(
function_exists(json_encode)){
            return 
json_encode($this->gamerdata);
        }else{
            
//non-native PHP JSON Encode...
            
if(!$this->JSON){
        require 
dirname(__FILE__).DIRECTORY_SEPARATOR."JSON.php";
                
$this->JSON = new Services_JSON();
            }
            return 
$this->JSON->encode($this->gamerdata);
        }
    }
    
    public function 
isValid(){
        if(!
$this->feed_parsed){
            
$this->parseXML();
        }
        return (
$this->gamerdata['State'] == 'Invalid' && $this->gamerdata['AccountStatus'] == 'Unknown') ? false true;
    }
}

1