content = new Content(&$this); $this->user = new User(&$this); $this->list = new Playlist(&$this); $this->activity = new Activity(&$this); } } class MagnifyXML{ // static utility class to get around SimpleXMLElement brain-damage public static $ns; public static function mapNS($simple){ self::$ns = $simple->getDocNamespaces(); } public static function extractLinks(){ $args = func_get_args(); $simple = array_shift($args); ( $simple instanceof SimpleXMLElement ) or die; $simple->registerXPathNameSpace('atom','http://www.w3.org/2005/Atom'); $links = array(); foreach($args as $rel){ $result = $simple->xpath("atom:link[@rel='$rel']/@href"); $links[] = $result ? (string) $result[0] : NULL; } return $links; } } abstract class Resource { protected $group,$parser,$dispatcher; function __construct($dispatcher){ $this->dispatcher = $dispatcher; $this->chain_construct(); } abstract function chain_construct(); protected function fetch($resource, $param = array() ){ define('BASE_URL','/api/'); $url='http://'.CHANNEL.'.'.BASE_URL .$this->group .'/' .$resource.'?'.http_build_query($param); $headers = array( "X-Magnify-Key: ".KEY ); // We use cURL rather than libXML's builtin retrieval // so that the key can be passed in the header $session = curl_init($url); curl_setopt($session,CURLOPT_RETURNTRANSFER,true); curl_setopt($session,CURLOPT_HTTPHEADER, $headers); $reply = curl_exec($session) or die("Could not retrieve Magnify XML"); curl_close($session); try{ $simple = @new SimpleXMLElement($reply); } catch(Exception $e){ die("Could not parse Magnify XML"); } MagnifyXML::mapNS($simple); return $simple; } // universal resources function show($id){ $simple = $this->fetch('show', array('id' => $id ) ); return call_user_func($this->parser,$simple->entry); } function browse($page = 1, $per_page = 10, $sort = 'recent'){ $simple = $this->fetch('browse', array( 'page' => $page, 'per_page' => $per_page, 'sort' => $sort ) ); return new Feed($simple, $this->parser); } function find($vq, $page = 1, $per_page = 10, $sort = 'recent'){ $simple = $this->fetch('find', array( 'page' => $page, 'per_page' => $per_page, 'vq' => $vq, sort => $sort ) ); return new Feed($simple, $this->parser); } } class Content extends Resource { function chain_construct(){ $this->group = 'content'; $this->parser = create_function( '$entry', ' $content_entry = new Content_Entry($entry); return $content_entry; ' ); } function user($id, $page = 1, $per_page = 10){ $simple = $this->fetch('user', array( 'page' => $page, 'per_page' => $per_page, 'id' => $id) ); return new Feed($simple, $this->parser); } } class User extends Resource { function chain_construct(){ $this->group = 'user'; $this->parser = create_function( '$entry', ' $user_entry = new User_Entry($entry); return $user_entry; ' ); } function browse(){ return NULL; } } class Playlist extends Resource { function chain_construct(){ $this->group = 'list'; $this->parser = create_function( '$entry', ' $list_entry = new Playlist_Entry($entry); return $list_entry; ' ); $this->show_parser = create_function( '$entry', ' $content_entry = new Content_Entry($entry); return $content_entry; ' ); } function find(){ return NULL; } function user($id, $page = 1, $per_page = 10){ $simple = $this->fetch('user', array( 'page' => $page, 'per_page' => $per_page, 'id' => $id ) ); return new Feed($simple, $this->parser); } function show($id, $page = 1, $per_page = 10, $sort = 'recent'){ $simple = $this->fetch('show', array( 'page' => $page, 'per_page' => $per_page, 'id' => $id, 'sort' => $sort ) ); return new Feed($simple, $this->show_parser); } } class Activity extends Resource { function chain_construct(){ $this->group = 'activity'; $this->parser = create_function( '$entry', ' $activity_entry = new Activity_Entry($entry); return $activity_entry; ' ); } function show(){ return NULL; } function find(){ return NULL; } function browse(){ return NULL; } function content($id, $page = 1, $per_page = 10){ $simple = $this->fetch('content',array( 'page' => $page, 'per_page' => $per_page, 'id' => $id ) ); return new Activity_Feed($simple, $this->parser); } } class Feed implements Iterator { public $title, $content, $updated; public $totalResults, $itemsPerPage, $startIndex; private $self, $alternate, $user; public $entries = array(); private $valid = FALSE; function rewind(){ $this->valid = (FALSE !== reset($this->entries)); } function current(){ return current($this->entries); } function key(){ return key($this->entries); } function next(){ $this->valid = (FALSE !== next($this->entries)); } function valid(){ return $this->valid; } function __construct($feed, $parser){ // normal Atom elements $this->title = (string) $feed->title; $this->content = (string) $feed->content; $this->updated = (string) $feed->updated; // opensearch elements $opensearch = $feed->children( MagnifyXML::$ns['opensearch'] ); $this->totalResults = (string) $opensearch->totalResults; $this->itemsPerPage = (string) $opensearch->itemsPerPage; $this->startIndex = (string) $opensearch->startIndex; // link elements list($this->self, $this->next, $this->previous) = MagnifyXML::extractLinks($feed, 'self','next','previous'); foreach($feed->entry as $entry){ $this->entries[] = call_user_func($parser,$entry); } } } class Activity_Feed extends Feed { // WARNING // the individual activity feeds returned by Activity_Feed methods are intended only as // convenient interfaces and still refer to entries in the parent feed // destroying the original object will render them useless private $clone_control = NULL; function __clone(){ if($this->clone_control){ foreach($this->entries as $key => $entry){ if($this->clone_control != $entry->activity){ unset($this->entries[$key]); } } unset($this->clone_control); } } public function getComments(){ $this->clone_control = "comment"; $comments = clone $this; return $comments; } public function getTags(){ $this->clone_control = "tagged"; $tags = clone $this; return $tags; } public function getReviews(){ $this->clone_control = "review"; $reviews = clone $this; return $reviews; } } abstract class Entry { public $id; function __construct(){ } function getId(){ return $this->id; } } class Content_Entry extends Entry { public $title, $content, $thumbnail, $author, $author_url, $author_id, $self, $alternate; private $iframe_url; function __construct($entry){ // normal Atom elements $this->title = (string) $entry->title; $this->content = (string) $entry->content; $this->updated = (string) $entry->updated; // magnify and media ns elements $magnify = $entry->children( MagnifyXML::$ns['magnify'] ); $media = $entry->children( MagnifyXML::$ns['media'] ); $this->id = (string) $magnify->id; $this->thumbnail = (string) $media->thumbnail->attributes()->url; $this->iframe_url = (string) $media->content->attributes()->url; // links list($this->self, $this->user, $this->alternate) = MagnifyXML::extractLinks($entry, 'self','user','alternate'); // author construct $this->author = (string) $entry->author->name; $this->author_id = (string) $entry->author->children( MagnifyXML::$ns['magnify'] )->id; $this->author_url = (string) $entry->author->uri; } function drawThumbnail($param = array() ){ $param{'width'} = isset($param{'width'}) ? $param{'width'} : 120; $param{'height'} = isset($param{'height'}) ? $param{'height'} : $param{'width'} / 1.33; return ''; } function drawIframe($param = array() ){ $param{'width'} = isset($param{'width'}) ? $param{'width'} : 320; $param{'height'} = isset($param{'height'}) ? $param{'height'} : $param{'width'} * 1.1; return ''; } } class Playlist_Entry extends Entry{ public $title, $updated, $author, $author_url, $author_id, $content, $thumbnail; function __construct($entry){ $this->title = (string) $entry->title; $this->content = (string) $entry->content; $this->updated = (string) $entry->updated; $magnify = $entry->children( MagnifyXML::$ns['magnify'] ); $media = $entry->children( MagnifyXML::$ns['media'] ); $opensearch = $entry->children( MagnifyXML::$ns['opensearch'] ); $this->id = (string) $magnify->id; $this->thumbnail = (string) $media->thumbnail->attributes()->url; $this->total = (string) $opensearch->totalResults; $this->author = (string) $entry->author->name; $this->author_id = (string) $entry->author->children( MagnifyXML::$ns['magnify'] )->id; $this->author_url = (string) $entry->author->uri; } function drawThumbnail($param = array() ){ $param{'width'} = isset($param{'width'}) ? $param{'width'} : 120; $param{'height'} = isset($param{'height'}) ? $param{'height'} : $param{'width'} / 1.33; return ''; } } class User_Entry extends Entry { public $name, $handle, $photo, $self, $content, $list, $alternate; function __construct($entry){ $this->name = (string) $entry->name; $magnify = $entry->children( MagnifyXML::$ns['magnify'] ); $this->handle = (string) $magnify->handle; $this->photo = (string) $magnify->photo; $this->id = (string) $magnify->id; } function drawThumbnail($param = array() ){ $param{'width'} = isset($param{'width'}) ? $param{'width'} : 70; $param{'height'} = isset($param{'height'}) ? $param{'height'} : $param{'width'}; return ''; } } class Activity_Entry extends Entry { public $author, $author_url, $author_id, $content, $activity, $tags, $rating, $updated; function __construct($entry){ $this->activity = (string) $entry->children( MagnifyXML::$ns['magnify'] )->activity; $this->updated = (string) $entry->updated; $matches = array(); if($this->activity == 'review' && $entry->content && preg_match('/Rating: (\d+)\.(.+)/',$entry->content,&$matches)){ $this->rating = $matches[1]; $this->content = $matches[2]; } else { $this->content = (string) $entry->content; } if($this->activity == 'tagged' && $entry->children( MagnifyXML::$ns['media'] )->keywords){ $this->tags = explode(',', $entry->children( MagnifyXML::$ns['media'] )->keywords); } $this->author = (string) $entry->author->name; $this->author_id = (string) $entry->author->children( MagnifyXML::$ns['magnify'] )->id; $this->author_url = (string) $entry->author->uri; } } ?>