From 6578e0e1afed8e8738bbcb31d200927e10074f11 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 25 Feb 2010 18:45:08 -0500 Subject: use new dedicated hcard method for Webfinger profile --- plugins/OStatus/actions/webfinger.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'plugins') diff --git a/plugins/OStatus/actions/webfinger.php b/plugins/OStatus/actions/webfinger.php index 34336a903..d3671962b 100644 --- a/plugins/OStatus/actions/webfinger.php +++ b/plugins/OStatus/actions/webfinger.php @@ -68,7 +68,7 @@ class WebfingerAction extends Action // hCard $xrd->links[] = array('rel' => 'http://microformats.org/profile/hcard', 'type' => 'text/html', - 'href' => common_profile_url($nick)); + 'href' => common_local_url('hcard', array('nickname' => $nick))); // XFN $xrd->links[] = array('rel' => 'http://gmpg.org/xfn/11', @@ -78,8 +78,8 @@ class WebfingerAction extends Action $xrd->links[] = array('rel' => 'describedby', 'type' => 'application/rdf+xml', 'href' => common_local_url('foaf', - array('nickname' => $nick))); - + array('nickname' => $nick))); + $salmon_url = common_local_url('salmon', array('id' => $this->user->id)); @@ -93,10 +93,10 @@ class WebfingerAction extends Action $magickey = new Magicsig(); $magickey->generate(); } - + $xrd->links[] = array('rel' => Magicsig::PUBLICKEYREL, 'href' => 'data:application/magic-public-key;'. $magickey->keypair); - + // TODO - finalize where the redirect should go on the publisher $url = common_local_url('ostatussub') . '?profile={uri}'; $xrd->links[] = array('rel' => 'http://ostatus.org/schema/1.0/subscribe', -- cgit v1.2.3-54-g00ecf From 45435a7c033d9c5acf0352bc44408667c5690198 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 26 Feb 2010 00:01:22 +0000 Subject: OStatus: if no available and no profileurl hint passed in, use object id if it's an HTTP(S) URL. Fixes profile link for Google accounts. --- plugins/OStatus/classes/Ostatus_profile.php | 2 ++ 1 file changed, 2 insertions(+) (limited to 'plugins') diff --git a/plugins/OStatus/classes/Ostatus_profile.php b/plugins/OStatus/classes/Ostatus_profile.php index f23017077..86a3c9354 100644 --- a/plugins/OStatus/classes/Ostatus_profile.php +++ b/plugins/OStatus/classes/Ostatus_profile.php @@ -1160,6 +1160,8 @@ class Ostatus_profile extends Memcached_DataObject $profile->profileurl = $object->link; } else if (array_key_exists('profileurl', $hints)) { $profile->profileurl = $hints['profileurl']; + } else if (Validate::uri($object->id, array('allowed_schemes' => array('http', 'https')))) { + $profile->profileurl = $object->id; } $profile->bio = self::getActivityObjectBio($object, $hints); -- cgit v1.2.3-54-g00ecf From 7922edb5b6c4ad55a1b81fa16c93e5656b676b26 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 25 Feb 2010 16:06:49 -0800 Subject: Add lots of fun avatars to our Atom output --- classes/Notice.php | 1 + lib/activity.php | 146 ++++++++++++++++++++++------ lib/atomnoticefeed.php | 5 + plugins/OStatus/classes/Ostatus_profile.php | 3 +- 4 files changed, 124 insertions(+), 31 deletions(-) (limited to 'plugins') diff --git a/classes/Notice.php b/classes/Notice.php index 46c5ebb37..ac4640534 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -1096,6 +1096,7 @@ class Notice extends Memcached_DataObject 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0', 'xmlns:georss' => 'http://www.georss.org/georss', 'xmlns:activity' => 'http://activitystrea.ms/spec/1.0/', + 'xmlns:media' => 'http://purl.org/syndication/atommedia', 'xmlns:poco' => 'http://portablecontacts.net/spec/1.0', 'xmlns:ostatus' => 'http://ostatus.org/schema/1.0'); } else { diff --git a/lib/activity.php b/lib/activity.php index 30cdc5a56..0f30e8bf5 100644 --- a/lib/activity.php +++ b/lib/activity.php @@ -465,6 +465,57 @@ class ActivityUtils } } +// XXX: Arg! This wouldn't be necessary if we used Avatars conistently +class AvatarLink +{ + public $url; + public $type; + public $size; + public $width; + + static function fromAvatar($avatar) + { + if (empty($avatar)) { + return null; + } + $alink = new AvatarLink(); + $alink->type = $avatar->mediatype; + $alink->height = $avatar->mediatype; + $alink->width = $avatar->width; + $alink->url = $avatar->displayUrl(); + return $alink; + } + + static function fromFilename($filename, $size) + { + $alink = new AvatarLink(); + $alink->url = $filename; + $alink->height = $size; + if (!empty($filename)) { + $alink->width = $size; + $alink->type = self::mediatype($filename); + } else { + $alink->url = User_group::defaultLogo($size); + $alink->type = 'image/png'; + } + return $alink; + } + + // yuck! + static function mediatype($filename) { + $ext = strtolower(end(explode('.', $filename))); + if ($ext == 'jpeg') { + $ext = 'jpg'; + } + // hope we don't support any others + $types = array('png', 'gif', 'jpg', 'jpeg'); + if (in_array($ext, $types)) { + return 'image/' . $ext; + } + return null; + } +} + /** * A noun-ish thing in the activity universe * @@ -521,7 +572,7 @@ class ActivityObject public $content; public $link; public $source; - public $avatar; + public $avatarLinks = array(); public $geopoint; public $poco; public $displayName; @@ -641,13 +692,40 @@ class ActivityObject $object->id = $profile->getUri(); $object->title = $profile->getBestName(); $object->link = $profile->profileurl; - $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); - if ($avatar) { - $object->avatar = $avatar->displayUrl(); + + $orig = $profile->getOriginalAvatar(); + + if (!empty($orig)) { + $object->avatarLinks[] = AvatarLink::fromAvatar($orig); + } + + $sizes = array( + AVATAR_PROFILE_SIZE, + AVATAR_STREAM_SIZE, + AVATAR_MINI_SIZE + ); + + foreach ($sizes as $size) { + + $alink = null; + $avatar = $profile->getAvatar($size); + + if (!empty($avatar)) { + $alink = AvatarLink::fromAvatar($avatar); + } else { + $alink = new AvatarLink(); + $alink->type = 'image/png'; + $alink->height = $size; + $alink->width = $size; + $alink->url = Avatar::defaultImage($size); + } + + $object->avatarLinks[] = $alink; } if (isset($profile->lat) && isset($profile->lon)) { - $object->geopoint = (float)$profile->lat . ' ' . (float)$profile->lon; + $object->geopoint = (float)$profile->lat + . ' ' . (float)$profile->lon; } $object->poco = PoCo::fromProfile($profile); @@ -663,13 +741,28 @@ class ActivityObject $object->id = $group->getUri(); $object->title = $group->getBestName(); $object->link = $group->getUri(); - $object->avatar = $group->getAvatar(); + + $object->avatarLinks[] = AvatarLink::fromFilename( + $group->homepage_logo, + AVATAR_PROFILE_SIZE + ); + + $object->avatarLinks[] = AvatarLink::fromFilename( + $group->stream_logo, + AVATAR_STREAM_SIZE + ); + + $object->avatarLinks[] = AvatarLink::fromFilename( + $group->mini_logo, + AVATAR_MINI_SIZE + ); $object->poco = PoCo::fromGroup($group); return $object; } + function asString($tag='activity:object') { $xs = new XMLStringer(true); @@ -705,29 +798,21 @@ class ActivityObject ); } - if ($this->type == ActivityObject::PERSON) { - $xs->element( - 'link', array( - 'type' => empty($this->avatar) ? 'image/png' : $this->avatar->mediatype, - 'rel' => 'avatar', - 'href' => empty($this->avatar) - ? Avatar::defaultImage(AVATAR_PROFILE_SIZE) - : $this->avatar - ), - null - ); - } - - // XXX: Gotta figure out mime-type! Gar. - - if ($this->type == ActivityObject::GROUP) { - $xs->element( - 'link', array( - 'rel' => 'avatar', - 'href' => $this->avatar - ), - null - ); + if ($this->type == ActivityObject::PERSON + || $this->type == ActivityObject::GROUP) { + + foreach ($this->avatarLinks as $avatar) { + $xs->element( + 'link', array( + 'rel' => 'avatar', + 'type' => $avatar->type, + 'media:width' => $avatar->width, + 'media:height' => $avatar->height, + 'href' => $avatar->url + ), + null + ); + } } if (!empty($this->geopoint)) { @@ -1038,7 +1123,8 @@ class Activity 'xmlns:activity' => 'http://activitystrea.ms/spec/1.0/', 'xmlns:georss' => 'http://www.georss.org/georss', 'xmlns:ostatus' => 'http://ostatus.org/schema/1.0', - 'xmlns:poco' => 'http://portablecontacts.net/spec/1.0'); + 'xmlns:poco' => 'http://portablecontacts.net/spec/1.0', + 'xmlns:media' => 'http://purl.org/syndication/atommedia'); } else { $attrs = array(); } diff --git a/lib/atomnoticefeed.php b/lib/atomnoticefeed.php index d2bf2a416..3c3556cb9 100644 --- a/lib/atomnoticefeed.php +++ b/lib/atomnoticefeed.php @@ -64,6 +64,11 @@ class AtomNoticeFeed extends Atom10Feed 'http://activitystrea.ms/spec/1.0/' ); + $this->addNamespace( + 'media', + 'http://purl.org/syndication/atommedia' + ); + $this->addNamespace( 'poco', 'http://portablecontacts.net/spec/1.0' diff --git a/plugins/OStatus/classes/Ostatus_profile.php b/plugins/OStatus/classes/Ostatus_profile.php index f23017077..7026d82f2 100644 --- a/plugins/OStatus/classes/Ostatus_profile.php +++ b/plugins/OStatus/classes/Ostatus_profile.php @@ -401,7 +401,8 @@ class Ostatus_profile extends Memcached_DataObject 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0', 'xmlns:georss' => 'http://www.georss.org/georss', 'xmlns:ostatus' => 'http://ostatus.org/schema/1.0', - 'xmlns:poco' => 'http://portablecontacts.net/spec/1.0'); + 'xmlns:poco' => 'http://portablecontacts.net/spec/1.0', + 'xmlns:media' => 'http://purl.org/syndication/atommedia'); $entry = new XMLStringer(); $entry->elementStart('entry', $attributes); -- cgit v1.2.3-54-g00ecf From 36f02f459b27a81e7017e3bb60b201677fd15a30 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 25 Feb 2010 19:11:39 -0500 Subject: add hkit for hCard parsing --- plugins/OStatus/extlib/hkit/hcard.profile.php | 105 ++++++ plugins/OStatus/extlib/hkit/hkit.class.php | 475 ++++++++++++++++++++++++++ 2 files changed, 580 insertions(+) create mode 100644 plugins/OStatus/extlib/hkit/hcard.profile.php create mode 100644 plugins/OStatus/extlib/hkit/hkit.class.php (limited to 'plugins') diff --git a/plugins/OStatus/extlib/hkit/hcard.profile.php b/plugins/OStatus/extlib/hkit/hcard.profile.php new file mode 100644 index 000000000..6ec0dc890 --- /dev/null +++ b/plugins/OStatus/extlib/hkit/hcard.profile.php @@ -0,0 +1,105 @@ +root_class = 'vcard'; + + $this->classes = array( + 'fn', array('honorific-prefix', 'given-name', 'additional-name', 'family-name', 'honorific-suffix'), + 'n', array('honorific-prefix', 'given-name', 'additional-name', 'family-name', 'honorific-suffix'), + 'adr', array('post-office-box', 'extended-address', 'street-address', 'postal-code', 'country-name', 'type', 'region', 'locality'), + 'label', 'bday', 'agent', 'nickname', 'photo', 'class', + 'email', array('type', 'value'), + 'category', 'key', 'logo', 'mailer', 'note', + 'org', array('organization-name', 'organization-unit'), + 'tel', array('type', 'value'), + 'geo', array('latitude', 'longitude'), + 'tz', 'uid', 'url', 'rev', 'role', 'sort-string', 'sound', 'title' + ); + + // classes that must only appear once per card + $this->singles = array( + 'fn' + ); + + // classes that are required (not strictly enforced - give at least one!) + $this->required = array( + 'fn' + ); + + $this->att_map = array( + 'fn' => array('IMG|alt'), + 'url' => array('A|href', 'IMG|src', 'AREA|href'), + 'photo' => array('IMG|src'), + 'bday' => array('ABBR|title'), + 'logo' => array('IMG|src'), + 'email' => array('A|href'), + 'geo' => array('ABBR|title') + ); + + + $this->callbacks = array( + 'url' => array($this, 'resolvePath'), + 'photo' => array($this, 'resolvePath'), + 'logo' => array($this, 'resolvePath'), + 'email' => array($this, 'resolveEmail') + ); + + + + function hKit_hcard_post($a) + { + + foreach ($a as &$vcard){ + + hKit_implied_n_optimization($vcard); + hKit_implied_n_from_fn($vcard); + + } + + return $a; + + } + + + function hKit_implied_n_optimization(&$vcard) + { + if (array_key_exists('fn', $vcard) && !is_array($vcard['fn']) && + !array_key_exists('n', $vcard) && (!array_key_exists('org', $vcard) || $vcard['fn'] != $vcard['org'])){ + + if (sizeof(explode(' ', $vcard['fn'])) == 2){ + $patterns = array(); + $patterns[] = array('/^(\S+),\s*(\S{1})$/', 2, 1); // Lastname, Initial + $patterns[] = array('/^(\S+)\s*(\S{1})\.*$/', 2, 1); // Lastname Initial(.) + $patterns[] = array('/^(\S+),\s*(\S+)$/', 2, 1); // Lastname, Firstname + $patterns[] = array('/^(\S+)\s*(\S+)$/', 1, 2); // Firstname Lastname + + foreach ($patterns as $pattern){ + if (preg_match($pattern[0], $vcard['fn'], $matches) === 1){ + $n = array(); + $n['given-name'] = $matches[$pattern[1]]; + $n['family-name'] = $matches[$pattern[2]]; + $vcard['n'] = $n; + + + break; + } + } + } + } + } + + + function hKit_implied_n_from_fn(&$vcard) + { + if (array_key_exists('fn', $vcard) && is_array($vcard['fn']) + && !array_key_exists('n', $vcard) && (!array_key_exists('org', $vcard) || $vcard['fn'] != $vcard['org'])){ + + $vcard['n'] = $vcard['fn']; + } + + if (array_key_exists('fn', $vcard) && is_array($vcard['fn'])){ + $vcard['fn'] = $vcard['fn']['text']; + } + } + +?> \ No newline at end of file diff --git a/plugins/OStatus/extlib/hkit/hkit.class.php b/plugins/OStatus/extlib/hkit/hkit.class.php new file mode 100644 index 000000000..c3a54cff6 --- /dev/null +++ b/plugins/OStatus/extlib/hkit/hkit.class.php @@ -0,0 +1,475 @@ +' . implode(', ', $missing) . ''); + + } + + + public function getByURL($profile='', $url='') + { + + if ($profile=='' || $url == '') return false; + + $this->loadProfile($profile); + + $source = $this->loadURL($url); + + if ($source){ + $tidy_xhtml = $this->tidyThis($source); + + $fragment = false; + + if (strrchr($url, '#')) + $fragment = array_pop(explode('#', $url)); + + $doc = $this->loadDoc($tidy_xhtml, $fragment); + $s = $this->processNodes($doc, $this->classes); + $s = $this->postProcess($profile, $s); + + return $s; + }else{ + return false; + } + } + + public function getByString($profile='', $input_xml='') + { + if ($profile=='' || $input_xml == '') return false; + + $this->loadProfile($profile); + + $doc = $this->loadDoc($input_xml); + $s = $this->processNodes($doc, $this->classes); + $s = $this->postProcess($profile, $s); + + return $s; + + } + + private function processNodes($items, $classes, $allow_includes=true){ + + $out = array(); + + foreach($items as $item){ + $data = array(); + + for ($i=0; $ixpath($xpath); + + if ($results){ + foreach ($results as $result){ + if (isset($classes[$i+1]) && is_array($classes[$i+1])){ + $nodes = $this->processNodes($results, $classes[$i+1]); + if (sizeof($nodes) > 0){ + $nodes = array_merge(array('text'=>$this->getNodeValue($result, $classes[$i])), $nodes); + $data[$classes[$i]] = $nodes; + }else{ + $data[$classes[$i]] = $this->getNodeValue($result, $classes[$i]); + } + + }else{ + if (isset($data[$classes[$i]])){ + if (is_array($data[$classes[$i]])){ + // is already an array - append + $data[$classes[$i]][] = $this->getNodeValue($result, $classes[$i]); + + }else{ + // make it an array + if ($classes[$i] == 'value'){ // unless it's the 'value' of a type/value pattern + $data[$classes[$i]] .= $this->getNodeValue($result, $classes[$i]); + }else{ + $old_val = $data[$classes[$i]]; + $data[$classes[$i]] = array($old_val, $this->getNodeValue($result, $classes[$i])); + $old_val = false; + } + } + }else{ + // set as normal value + $data[$classes[$i]] = $this->getNodeValue($result, $classes[$i]); + + } + } + + // td@headers pattern + if (strtoupper(dom_import_simplexml($result)->tagName)== "TD" && $result['headers']){ + $include_ids = explode(' ', $result['headers']); + $doc = $this->doc; + foreach ($include_ids as $id){ + $xpath = "//*[@id='$id']/.."; + $includes = $doc->xpath($xpath); + foreach ($includes as $include){ + $tmp = $this->processNodes($include, $this->classes); + if (is_array($tmp)) $data = array_merge($data, $tmp); + } + } + } + } + } + } + $result = false; + } + + // include-pattern + if ($allow_includes){ + $xpath = ".//*[contains(concat(' ',normalize-space(@class),' '),' include ')]"; + $results = $item->xpath($xpath); + + if ($results){ + foreach ($results as $result){ + $tagName = strtoupper(dom_import_simplexml($result)->tagName); + if ((($tagName == "OBJECT" && $result['data']) || ($tagName == "A" && $result['href'])) + && preg_match('/\binclude\b/', $result['class'])){ + $att = ($tagName == "OBJECT" ? 'data' : 'href'); + $id = str_replace('#', '', $result[$att]); + $doc = $this->doc; + $xpath = "//*[@id='$id']"; + $includes = $doc->xpath($xpath); + foreach ($includes as $include){ + $include = simplexml_load_string(''.$include->asXML().''); // don't ask. + $tmp = $this->processNodes($include, $this->classes, false); + if (is_array($tmp)) $data = array_merge($data, $tmp); + } + } + } + } + } + $out[] = $data; + } + + if (sizeof($out) > 1){ + return $out; + }else if (isset($data)){ + return $data; + }else{ + return array(); + } + } + + + private function getNodeValue($node, $className) + { + + $tag_name = strtoupper(dom_import_simplexml($node)->tagName); + $s = false; + + // ignore DEL tags + if ($tag_name == 'DEL') return $s; + + // look up att map values + if (array_key_exists($className, $this->att_map)){ + + foreach ($this->att_map[$className] as $map){ + if (preg_match("/$tag_name\|/", $map)){ + $s = ''.$node[array_pop($foo = explode('|', $map))]; + } + } + } + + // if nothing and OBJ, try data. + if (!$s && $tag_name=='OBJECT' && $node['data']) $s = ''.$node['data']; + + // if nothing and IMG, try alt. + if (!$s && $tag_name=='IMG' && $node['alt']) $s = ''.$node['alt']; + + // if nothing and AREA, try alt. + if (!$s && $tag_name=='AREA' && $node['alt']) $s = ''.$node['alt']; + + //if nothing and not A, try title. + if (!$s && $tag_name!='A' && $node['title']) $s = ''.$node['title']; + + + // if nothing found, go with node text + $s = ($s ? $s : implode(array_filter($node->xpath('child::node()'), array(&$this, "filterBlankValues")), ' ')); + + // callbacks + if (array_key_exists($className, $this->callbacks)){ + $s = preg_replace_callback('/.*/', $this->callbacks[$className], $s, 1); + } + + // trim and remove line breaks + if ($tag_name != 'PRE'){ + $s = trim(preg_replace('/[\r\n\t]+/', '', $s)); + $s = trim(preg_replace('/(\s{2})+/', ' ', $s)); + } + + return $s; + } + + private function filterBlankValues($s){ + return preg_match("/\w+/", $s); + } + + + private function tidyThis($source) + { + switch ( $this->tidy_mode ) + { + case 'exec': + $tmp_file = $this->tmp_dir.md5($source).'.txt'; + file_put_contents($tmp_file, $source); + exec("tidy -utf8 -indent -asxhtml -numeric -bare -quiet $tmp_file", $tidy); + unlink($tmp_file); + return implode("\n", $tidy); + break; + + case 'php': + $tidy = tidy_parse_string($source); + return tidy_clean_repair($tidy); + break; + + default: + return $source; + break; + } + + } + + + private function loadProfile($profile) + { + require_once("$profile.profile.php"); + } + + + private function loadDoc($input_xml, $fragment=false) + { + $xml = simplexml_load_string($input_xml); + + $this->doc = $xml; + + if ($fragment){ + $doc = $xml->xpath("//*[@id='$fragment']"); + $xml = simplexml_load_string($doc[0]->asXML()); + $doc = null; + } + + // base tag + if ($xml->head->base['href']) $this->base = $xml->head->base['href']; + + // xml:base attribute - PITA with SimpleXML + preg_match('/xml:base="(.*)"/', $xml->asXML(), $matches); + if (is_array($matches) && sizeof($matches)>1) $this->base = $matches[1]; + + return $xml->xpath("//*[contains(concat(' ',normalize-space(@class),' '),' $this->root_class ')]"); + + } + + + private function loadURL($url) + { + $this->url = $url; + + if ($this->tidy_mode == 'proxy' && $this->tidy_proxy != ''){ + $url = $this->tidy_proxy . $url; + } + + return @file_get_contents($url); + + } + + + private function postProcess($profile, $s) + { + $required = $this->required; + + if (is_array($s) && array_key_exists($required[0], $s)){ + $s = array($s); + } + + $s = $this->dedupeSingles($s); + + if (function_exists('hKit_'.$profile.'_post')){ + $s = call_user_func('hKit_'.$profile.'_post', $s); + } + + $s = $this->removeTextVals($s); + + return $s; + } + + + private function resolvePath($filepath) + { // ugly code ahoy: needs a serious tidy up + + $filepath = $filepath[0]; + + $base = $this->base; + $url = $this->url; + + if ($base != '' && strpos($base, '://') !== false) + $url = $base; + + $r = parse_url($url); + $domain = $r['scheme'] . '://' . $r['host']; + + if (!isset($r['path'])) $r['path'] = '/'; + $path = explode('/', $r['path']); + $file = explode('/', $filepath); + $new = array(''); + + if (strpos($filepath, '://') !== false || strpos($filepath, 'data:') !== false){ + return $filepath; + } + + if ($file[0] == ''){ + // absolute path + return ''.$domain . implode('/', $file); + }else{ + // relative path + if ($path[sizeof($path)-1] == '') array_pop($path); + if (strpos($path[sizeof($path)-1], '.') !== false) array_pop($path); + + foreach ($file as $segment){ + if ($segment == '..'){ + array_pop($path); + }else{ + $new[] = $segment; + } + } + return ''.$domain . implode('/', $path) . implode('/', $new); + } + } + + private function resolveEmail($v) + { + $parts = parse_url($v[0]); + return ($parts['path']); + } + + + private function dedupeSingles($s) + { + $singles = $this->singles; + + foreach ($s as &$item){ + foreach ($singles as $classname){ + if (array_key_exists($classname, $item) && is_array($item[$classname])){ + if (isset($item[$classname][0])) $item[$classname] = $item[$classname][0]; + } + } + } + + return $s; + } + + private function removeTextVals($s) + { + foreach ($s as $key => &$val){ + if ($key){ + $k = $key; + }else{ + $k = ''; + } + + if (is_array($val)){ + $val = $this->removeTextVals($val); + }else{ + if ($k == 'text'){ + $val = ''; + } + } + } + + return array_filter($s); + } + + } + + +?> \ No newline at end of file -- cgit v1.2.3-54-g00ecf From cc0670791ef07826055b461e10e64d65ec9e6547 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 25 Feb 2010 19:58:18 -0500 Subject: use new hcard method for webfinger --- plugins/OStatus/actions/webfinger.php | 2 +- plugins/OStatus/lib/webfinger.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/OStatus/actions/webfinger.php b/plugins/OStatus/actions/webfinger.php index d3671962b..e292ccec9 100644 --- a/plugins/OStatus/actions/webfinger.php +++ b/plugins/OStatus/actions/webfinger.php @@ -66,7 +66,7 @@ class WebfingerAction extends Action 'type' => 'application/atom+xml'); // hCard - $xrd->links[] = array('rel' => 'http://microformats.org/profile/hcard', + $xrd->links[] = array('rel' => Webfinger::HCARD, 'type' => 'text/html', 'href' => common_local_url('hcard', array('nickname' => $nick))); diff --git a/plugins/OStatus/lib/webfinger.php b/plugins/OStatus/lib/webfinger.php index 8a5037629..8d7040310 100644 --- a/plugins/OStatus/lib/webfinger.php +++ b/plugins/OStatus/lib/webfinger.php @@ -37,6 +37,7 @@ class Webfinger { const PROFILEPAGE = 'http://webfinger.net/rel/profile-page'; const UPDATESFROM = 'http://schemas.google.com/g/2010#updates-from'; + const HCARD = 'http://microformats.org/profile/hcard'; /** * Perform a webfinger lookup given an account. -- cgit v1.2.3-54-g00ecf From 894b221e8aec57768d6804ee3bf53c85196e09bf Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 25 Feb 2010 19:58:51 -0500 Subject: Parse an hcard for hints, if available --- plugins/OStatus/classes/Ostatus_profile.php | 119 ++++++++++++++++++++++++---- 1 file changed, 104 insertions(+), 15 deletions(-) (limited to 'plugins') diff --git a/plugins/OStatus/classes/Ostatus_profile.php b/plugins/OStatus/classes/Ostatus_profile.php index f23017077..2d517ed22 100644 --- a/plugins/OStatus/classes/Ostatus_profile.php +++ b/plugins/OStatus/classes/Ostatus_profile.php @@ -644,7 +644,6 @@ class Ostatus_profile extends Memcached_DataObject 'groups' => array(), 'tags' => array()); - // Check for optional attributes... if (!empty($activity->time)) { @@ -1155,7 +1154,13 @@ class Ostatus_profile extends Memcached_DataObject $orig = clone($profile); $profile->nickname = self::getActivityObjectNickname($object, $hints); - $profile->fullname = $object->title; + + if (!empty($object->title)) { + $profile->fullname = $object->title; + } else if (array_key_exists('fullname', $hints)) { + $profile->fullname = $hints['fullname']; + } + if (!empty($object->link)) { $profile->profileurl = $object->link; } else if (array_key_exists('profileurl', $hints)) { @@ -1228,12 +1233,16 @@ class Ostatus_profile extends Memcached_DataObject { $location = null; - if (!empty($object->poco)) { - if (isset($object->poco->address->formatted)) { - $location = $object->poco->address->formatted; - if (mb_strlen($location) > 255) { - $location = mb_substr($note, 0, 255 - 3) . ' … '; - } + if (!empty($object->poco) && + isset($object->poco->address->formatted)) { + $location = $object->poco->address->formatted; + } else if (array_key_exists('location', $hints)) { + $location = $hints['location']; + } + + if (!empty($location)) { + if (mb_strlen($location) > 255) { + $location = mb_substr($note, 0, 255 - 3) . ' … '; } } @@ -1248,13 +1257,16 @@ class Ostatus_profile extends Memcached_DataObject if (!empty($object->poco)) { $note = $object->poco->note; - if (!empty($note)) { - if (mb_strlen($note) > Profile::maxBio()) { - // XXX: truncate ok? - $bio = mb_substr($note, 0, Profile::maxBio() - 3) . ' … '; - } else { - $bio = $note; - } + } else if (array_key_exists('bio', $hints)) { + $note = $hints['bio']; + } + + if (!empty($note)) { + if (Profile::bioTooLong($note)) { + // XXX: truncate ok? + $bio = mb_substr($note, 0, Profile::maxBio() - 3) . ' … '; + } else { + $bio = $note; } } @@ -1270,10 +1282,15 @@ class Ostatus_profile extends Memcached_DataObject return common_nicknamize($object->poco->preferredUsername); } } + if (!empty($object->nickname)) { return common_nicknamize($object->nickname); } + if (array_key_exists('nickname', $hints)) { + return $hints['nickname']; + } + // Try the definitive ID $nickname = self::nicknameFromURI($object->id); @@ -1347,6 +1364,9 @@ class Ostatus_profile extends Memcached_DataObject case Webfinger::UPDATESFROM: $feedUrl = $link['href']; break; + case Webfinger::HCARD: + $hcardUrl = $link['href']; + break; default: common_log(LOG_NOTICE, "Don't know what to do with rel = '{$link['rel']}'"); break; @@ -1358,6 +1378,12 @@ class Ostatus_profile extends Memcached_DataObject 'feedurl' => $feedUrl, 'salmon' => $salmonEndpoint); + if (isset($hcardUrl)) { + $hcardHints = self::slurpHcard($hcardUrl); + // Note: Webfinger > hcard + $hints = array_merge($hcardHints, $hints); + } + // If we got a feed URL, try that if (isset($feedUrl)) { @@ -1464,4 +1490,67 @@ class Ostatus_profile extends Memcached_DataObject return $file; } + + protected static function slurpHcard($url) + { + set_include_path(get_include_path() . PATH_SEPARATOR . INSTALLDIR . '/plugins/OStatus/extlib/hkit/'); + require_once('hkit.class.php'); + + $h = new hKit; + + // Google Buzz hcards need to be tidied. Probably others too. + + $h->tidy_mode = 'proxy'; // 'proxy', 'exec', 'php' or 'none' + + // Get by URL + $hcards = $h->getByURL('hcard', $url); + + if (empty($hcards)) { + return array(); + } + + // @fixme more intelligent guess on multi-hcard pages + $hcard = $hcards[0]; + + $hints = array(); + + $hints['profileurl'] = $url; + + if (array_key_exists('nickname', $hcard)) { + $hints['nickname'] = $hcard['nickname']; + } + + if (array_key_exists('fn', $hcard)) { + $hints['fullname'] = $hcard['fn']; + } else if (array_key_exists('n', $hcard)) { + $hints['fullname'] = implode(' ', $hcard['n']); + } + + if (array_key_exists('photo', $hcard)) { + $hints['avatar'] = $hcard['photo']; + } + + if (array_key_exists('note', $hcard)) { + $hints['bio'] = $hcard['note']; + } + + if (array_key_exists('adr', $hcard)) { + if (is_string($hcard['adr'])) { + $hints['location'] = $hcard['adr']; + } else if (is_array($hcard['adr'])) { + $hints['location'] = implode(' ', $hcard['adr']); + } + } + + if (array_key_exists('url', $hcard)) { + if (is_string($hcard['url'])) { + $hints['homepage'] = $hcard['url']; + } else if (is_array($hcard['adr'])) { + // HACK get the last one; that's how our hcards look + $hints['homepage'] = $hcard['url'][count($hcard['url'])-1]; + } + } + + return $hints; + } } -- cgit v1.2.3-54-g00ecf From c693365ae7a27f82afef1765610c41a4bff33726 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 25 Feb 2010 20:29:52 -0500 Subject: cache results of webfinger lookups --- plugins/OStatus/classes/Ostatus_profile.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'plugins') diff --git a/plugins/OStatus/classes/Ostatus_profile.php b/plugins/OStatus/classes/Ostatus_profile.php index 8ca28432b..ad9170f5b 100644 --- a/plugins/OStatus/classes/Ostatus_profile.php +++ b/plugins/OStatus/classes/Ostatus_profile.php @@ -1338,11 +1338,26 @@ class Ostatus_profile extends Memcached_DataObject public static function ensureWebfinger($addr) { + // First, try the cache + + $uri = self::cacheGet(sprintf('ostatus_profile:webfinger:%s', $addr)); + + if ($uri !== false) { + if (is_null($uri)) { + return null; + } + $oprofile = Ostatus_profile::staticGet('uri', $uri); + if (!empty($oprofile)) { + return $oprofile; + } + } + // First, look it up $oprofile = Ostatus_profile::staticGet('uri', 'acct:'.$addr); if (!empty($oprofile)) { + self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri); return $oprofile; } @@ -1353,6 +1368,7 @@ class Ostatus_profile extends Memcached_DataObject $result = $wf->lookup($addr); if (!$result) { + self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), null); return null; } @@ -1392,6 +1408,7 @@ class Ostatus_profile extends Memcached_DataObject if (isset($feedUrl)) { try { $oprofile = self::ensureProfile($feedUrl, $hints); + self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri); return $oprofile; } catch (Exception $e) { common_log(LOG_WARNING, "Failed creating profile from feed URL '$feedUrl': " . $e->getMessage()); @@ -1404,6 +1421,7 @@ class Ostatus_profile extends Memcached_DataObject if (isset($profileUrl)) { try { $oprofile = self::ensureProfile($profileUrl, $hints); + self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri); return $oprofile; } catch (Exception $e) { common_log(LOG_WARNING, "Failed creating profile from profile URL '$profileUrl': " . $e->getMessage()); @@ -1455,6 +1473,7 @@ class Ostatus_profile extends Memcached_DataObject throw new Exception("Couldn't save ostatus_profile for '$addr'"); } + self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri); return $oprofile; } -- cgit v1.2.3-54-g00ecf From a43598c31ecee2ca77d8c686382c29ee5a0d42b1 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 25 Feb 2010 21:07:24 -0500 Subject: cache Web responses in Webfinger library --- plugins/OStatus/lib/webfinger.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/OStatus/lib/webfinger.php b/plugins/OStatus/lib/webfinger.php index 8d7040310..4b777c9a0 100644 --- a/plugins/OStatus/lib/webfinger.php +++ b/plugins/OStatus/lib/webfinger.php @@ -81,11 +81,14 @@ class Webfinger function getServiceLinks($domain) { $url = 'http://'. $domain .'/.well-known/host-meta'; + $content = $this->fetchURL($url); + if (empty($content)) { common_log(LOG_DEBUG, 'Error fetching host-meta'); return false; } + $result = XRD::parse($content); // Ensure that the host == domain (spec may include signing later) @@ -119,6 +122,11 @@ class Webfinger function fetchURL($url) { try { + $c = Cache::instance(); + $content = $c->get('webfinger:url:'.$url); + if ($content !== false) { + return $content; + } $client = new HTTPClient(); $response = $client->get($url); } catch (HTTP_Request2_Exception $e) { @@ -129,7 +137,11 @@ class Webfinger return false; } - return $response->getBody(); + $body = $response->getBody(); + + $c->set('webfinger:url:'.$url, $body); + + return $body; } function applyTemplate($template, $id) -- cgit v1.2.3-54-g00ecf From e197208a4a2ab742df481968e30cd99678be96ad Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 25 Feb 2010 21:07:52 -0500 Subject: info about discovery in Ostatus_profile::ensureWebfinger() --- plugins/OStatus/classes/Ostatus_profile.php | 2 ++ 1 file changed, 2 insertions(+) (limited to 'plugins') diff --git a/plugins/OStatus/classes/Ostatus_profile.php b/plugins/OStatus/classes/Ostatus_profile.php index ad9170f5b..26d776d52 100644 --- a/plugins/OStatus/classes/Ostatus_profile.php +++ b/plugins/OStatus/classes/Ostatus_profile.php @@ -1407,6 +1407,7 @@ class Ostatus_profile extends Memcached_DataObject if (isset($feedUrl)) { try { + common_log(LOG_INFO, "Discovery on acct:$addr with feed URL $feedUrl"); $oprofile = self::ensureProfile($feedUrl, $hints); self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri); return $oprofile; @@ -1420,6 +1421,7 @@ class Ostatus_profile extends Memcached_DataObject if (isset($profileUrl)) { try { + common_log(LOG_INFO, "Discovery on acct:$addr with profile URL $profileUrl"); $oprofile = self::ensureProfile($profileUrl, $hints); self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri); return $oprofile; -- cgit v1.2.3-54-g00ecf From 2feb09f4346e54805f68a9f677f5a94340875d8e Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 25 Feb 2010 18:51:44 -0800 Subject: OStatus: pull best-sized avatar image (96x96 if found, otherwise largest, otherwise if none labeled takes the first) --- lib/activity.php | 43 +++++++++++++++++++++++++++-- plugins/OStatus/classes/Ostatus_profile.php | 16 +++++++++-- 2 files changed, 55 insertions(+), 4 deletions(-) (limited to 'plugins') diff --git a/lib/activity.php b/lib/activity.php index 0f30e8bf5..b64a82f0a 100644 --- a/lib/activity.php +++ b/lib/activity.php @@ -360,6 +360,25 @@ class ActivityUtils return null; } + static function getLinks(DOMNode $element, $rel, $type=null) + { + $links = $element->getElementsByTagnameNS(self::ATOM, self::LINK); + $out = array(); + + foreach ($links as $link) { + + $linkRel = $link->getAttribute(self::REL); + $linkType = $link->getAttribute(self::TYPE); + + if ($linkRel == $rel && + (is_null($type) || $linkType == $type)) { + $out[] = $link; + } + } + + return $out; + } + /** * Gets the first child element with the given tag * @@ -472,6 +491,24 @@ class AvatarLink public $type; public $size; public $width; + public $height; + + function __construct($element=null) + { + if ($element) { + // @fixme use correct namespaces + $this->url = $element->getAttribute('href'); + $this->type = $element->getAttribute('type'); + $width = $element->getAttribute('media:width'); + if ($width != null) { + $this->width = intval($width); + } + $height = $element->getAttribute('media:height'); + if ($height != null) { + $this->height = intval($height); + } + } + } static function fromAvatar($avatar) { @@ -640,8 +677,10 @@ class ActivityObject if ($this->type == self::PERSON || $this->type == self::GROUP) { $this->displayName = $this->title; - // @fixme we may have multiple avatars with different resolutions specified - $this->avatar = ActivityUtils::getLink($element, 'avatar'); + $avatars = ActivityUtils::getLinks($element, 'avatar'); + foreach ($avatars as $link) { + $this->avatarLinks[] = new AvatarLink($link); + } $this->poco = new PoCo($element); } diff --git a/plugins/OStatus/classes/Ostatus_profile.php b/plugins/OStatus/classes/Ostatus_profile.php index ad9170f5b..9b7be4e9a 100644 --- a/plugins/OStatus/classes/Ostatus_profile.php +++ b/plugins/OStatus/classes/Ostatus_profile.php @@ -912,8 +912,20 @@ class Ostatus_profile extends Memcached_DataObject protected static function getActivityObjectAvatar($object, $hints=array()) { - if ($object->avatar) { - return $object->avatar; + if ($object->avatarLinks) { + $best = false; + // Take the exact-size avatar, or the largest avatar, or the first avatar if all sizeless + foreach ($object->avatarLinks as $avatar) { + if ($avatar->width == AVATAR_PROFILE_SIZE && $avatar->height = AVATAR_PROFILE_SIZE) { + // Exact match! + $best = $avatar; + break; + } + if (!$best || $avatar->width > $best->width) { + $best = $avatar; + } + } + return $best->url; } else if (array_key_exists('avatar', $hints)) { return $hints['avatar']; } -- cgit v1.2.3-54-g00ecf From d8d8d59a03ef3fa12a0ea668b4a2f383f80486dc Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 25 Feb 2010 18:55:11 -0800 Subject: - Updates to use new activity object factories - Prune obsolete feed creation method --- plugins/OStatus/classes/Ostatus_profile.php | 104 ++-------------------------- 1 file changed, 5 insertions(+), 99 deletions(-) (limited to 'plugins') diff --git a/plugins/OStatus/classes/Ostatus_profile.php b/plugins/OStatus/classes/Ostatus_profile.php index ad9170f5b..c3ea042ff 100644 --- a/plugins/OStatus/classes/Ostatus_profile.php +++ b/plugins/OStatus/classes/Ostatus_profile.php @@ -150,27 +150,7 @@ class Ostatus_profile extends Memcached_DataObject function asActivityObject() { if ($this->isGroup()) { - $object = new ActivityObject(); - $object->type = 'http://activitystrea.ms/schema/1.0/group'; - $object->id = $this->uri; - $self = $this->localGroup(); - - // @fixme put a standard getAvatar() interface on groups too - if ($self->homepage_logo) { - $object->avatar = $self->homepage_logo; - $map = array('png' => 'image/png', - 'jpg' => 'image/jpeg', - 'jpeg' => 'image/jpeg', - 'gif' => 'image/gif'); - $extension = pathinfo(parse_url($object->avatar, PHP_URL_PATH), PATHINFO_EXTENSION); - if (isset($map[$extension])) { - // @fixme this ain't used/saved yet - $object->avatarType = $map[$extension]; - } - } - - $object->link = $this->uri; // @fixme accurate? - return $object; + return ActivityObject::fromGroup($this->localGroup()); } else { return ActivityObject::fromProfile($this->localProfile()); } @@ -189,57 +169,13 @@ class Ostatus_profile extends Memcached_DataObject */ function asActivityNoun($element) { - $xs = new XMLStringer(true); - $avatarHref = Avatar::defaultImage(AVATAR_PROFILE_SIZE); - $avatarType = 'image/png'; if ($this->isGroup()) { - $type = 'http://activitystrea.ms/schema/1.0/group'; - $self = $this->localGroup(); - - // @fixme put a standard getAvatar() interface on groups too - if ($self->homepage_logo) { - $avatarHref = $self->homepage_logo; - $map = array('png' => 'image/png', - 'jpg' => 'image/jpeg', - 'jpeg' => 'image/jpeg', - 'gif' => 'image/gif'); - $extension = pathinfo(parse_url($avatarHref, PHP_URL_PATH), PATHINFO_EXTENSION); - if (isset($map[$extension])) { - $avatarType = $map[$extension]; - } - } + $noun = ActivityObject::fromGroup($this->localGroup()); + return $noun->asString('activity:' . $element); } else { - $type = 'http://activitystrea.ms/schema/1.0/person'; - $self = $this->localProfile(); - $avatar = $self->getAvatar(AVATAR_PROFILE_SIZE); - if ($avatar) { - $avatarHref = $avatar->url; - $avatarType = $avatar->mediatype; - } + $noun = ActivityObject::fromProfile($this->localProfile()); + return $noun->asString('activity:' . $element); } - $xs->elementStart('activity:' . $element); - $xs->element( - 'activity:object-type', - null, - $type - ); - $xs->element( - 'id', - null, - $this->uri); // ? - $xs->element('title', null, $self->getBestName()); - - $xs->element( - 'link', array( - 'type' => $avatarType, - 'href' => $avatarHref - ), - '' - ); - - $xs->elementEnd('activity:' . $element); - - return $xs->getString(); } /** @@ -486,36 +422,6 @@ class Ostatus_profile extends Memcached_DataObject } } - function atomFeed($actor) - { - $feed = new Atom10Feed(); - // @fixme should these be set up somewhere else? - $feed->addNamespace('activity', 'http://activitystrea.ms/spec/1.0/'); - $feed->addNamespace('thr', 'http://purl.org/syndication/thread/1.0'); - $feed->addNamespace('georss', 'http://www.georss.org/georss'); - $feed->addNamespace('ostatus', 'http://ostatus.org/schema/1.0'); - - $taguribase = common_config('integration', 'taguri'); - $feed->setId("tag:{$taguribase}:UserTimeline:{$actor->id}"); // ??? - - $feed->setTitle($actor->getBestName() . ' timeline'); // @fixme - $feed->setUpdated(time()); - $feed->setPublished(time()); - - $feed->addLink(common_local_url('ApiTimelineUser', - array('id' => $actor->id, - 'type' => 'atom')), - array('rel' => 'self', - 'type' => 'application/atom+xml')); - - $feed->addLink(common_local_url('userbyid', - array('id' => $actor->id)), - array('rel' => 'alternate', - 'type' => 'text/html')); - - return $feed; - } - /** * Read and post notices for updates from the feed. * Currently assumes that all items in the feed are new, -- cgit v1.2.3-54-g00ecf From 2528bb452b4ed27cc8685f5c8d900fe0742ef229 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 25 Feb 2010 19:48:28 -0800 Subject: OStatus: clean up known-URL hinting during profile setup, saves some extra HTTP hits we were getting when mentioning Buzz feeds. --- plugins/OStatus/classes/Ostatus_profile.php | 82 +++++++++++++++-------------- 1 file changed, 43 insertions(+), 39 deletions(-) (limited to 'plugins') diff --git a/plugins/OStatus/classes/Ostatus_profile.php b/plugins/OStatus/classes/Ostatus_profile.php index 75b4bef41..c462fead6 100644 --- a/plugins/OStatus/classes/Ostatus_profile.php +++ b/plugins/OStatus/classes/Ostatus_profile.php @@ -791,11 +791,18 @@ class Ostatus_profile extends Memcached_DataObject { // Get the canonical feed URI and check it $discover = new FeedDiscovery(); - $feeduri = $discover->discoverFromURL($profile_uri); + if ($hints['feedurl']) { + $feeduri = $hints['feedurl']; + $feeduri = $discover->discoverFromFeedURL($feeduri); + } else { + $feeduri = $discover->discoverFromURL($profile_uri); + $hints['feedurl'] = $feeduri; + } - //$feedsub = FeedSub::ensureFeed($feeduri, $discover->feed); $huburi = $discover->getAtomLink('hub'); + $hints['hub'] = $huburi; $salmonuri = $discover->getAtomLink('salmon'); + $hints['salmon'] = $salmonuri; if (!$huburi) { // We can only deal with folks with a PuSH hub @@ -810,7 +817,7 @@ class Ostatus_profile extends Memcached_DataObject if (!empty($subject)) { $subjObject = new ActivityObject($subject); - return self::ensureActivityObjectProfile($subjObject, $feeduri, $salmonuri, $hints); + return self::ensureActivityObjectProfile($subjObject, $hints); } // Otherwise, try the feed author @@ -819,7 +826,7 @@ class Ostatus_profile extends Memcached_DataObject if (!empty($author)) { $authorObject = new ActivityObject($author); - return self::ensureActivityObjectProfile($authorObject, $feeduri, $salmonuri, $hints); + return self::ensureActivityObjectProfile($authorObject, $hints); } // Sheesh. Not a very nice feed! Let's try fingerpoken in the @@ -835,7 +842,7 @@ class Ostatus_profile extends Memcached_DataObject if (!empty($actor)) { $actorObject = new ActivityObject($actor); - return self::ensureActivityObjectProfile($actorObject, $feeduri, $salmonuri, $hints); + return self::ensureActivityObjectProfile($actorObject, $hints); } @@ -843,7 +850,7 @@ class Ostatus_profile extends Memcached_DataObject if (!empty($author)) { $authorObject = new ActivityObject($author); - return self::ensureActivityObjectProfile($authorObject, $feeduri, $salmonuri, $hints); + return self::ensureActivityObjectProfile($authorObject, $hints); } } @@ -988,18 +995,18 @@ class Ostatus_profile extends Memcached_DataObject * @return Ostatus_profile */ - public static function ensureActorProfile($activity, $feeduri=null, $salmonuri=null) + public static function ensureActorProfile($activity, $hints=array()) { - return self::ensureActivityObjectProfile($activity->actor, $feeduri, $salmonuri); + return self::ensureActivityObjectProfile($activity->actor, $hints); } - public static function ensureActivityObjectProfile($object, $feeduri=null, $salmonuri=null, $hints=array()) + public static function ensureActivityObjectProfile($object, $hints=array()) { $profile = self::getActivityObjectProfile($object); if ($profile) { $profile->updateFromActivityObject($object, $hints); } else { - $profile = self::createActivityObjectProfile($object, $feeduri, $salmonuri, $hints); + $profile = self::createActivityObjectProfile($object, $hints); } return $profile; } @@ -1045,58 +1052,55 @@ class Ostatus_profile extends Memcached_DataObject * @fixme validate stuff somewhere */ - protected static function createActorProfile($activity, $feeduri=null, $salmonuri=null) - { - $actor = $activity->actor; - - self::createActivityObjectProfile($actor, $feeduri, $salmonuri); - } - /** * Create local ostatus_profile and profile/user_group entries for * the provided remote user or group. * * @param ActivityObject $object - * @param string $feeduri - * @param string $salmonuri * @param array $hints * - * @fixme fold $feeduri/$salmonuri into $hints * @return Ostatus_profile */ - protected static function createActivityObjectProfile($object, $feeduri=null, $salmonuri=null, $hints=array()) + protected static function createActivityObjectProfile($object, $hints=array()) { - $homeuri = $object->id; + $homeuri = $object->id; + $discover = false; if (!$homeuri) { common_log(LOG_DEBUG, __METHOD__ . " empty actor profile URI: " . var_export($activity, true)); throw new ServerException("No profile URI"); } - if (empty($feeduri)) { - if (array_key_exists('feedurl', $hints)) { - $feeduri = $hints['feedurl']; - } + if (array_key_exists('feedurl', $hints)) { + $feeduri = $hints['feedurl']; + } else { + $discover = new FeedDiscovery(); + $feeduri = $discover->discoverFromURL($homeuri); } - if (empty($salmonuri)) { - if (array_key_exists('salmon', $hints)) { - $salmonuri = $hints['salmon']; + if (array_key_exists('salmon', $hints)) { + $salmonuri = $hints['salmon']; + } else { + if (!$discover) { + $discover = new FeedDiscovery(); + $discover->discoverFromFeedURL($hints['feedurl']); } + $salmonuri = $discover->getAtomLink('salmon'); } - if (!$feeduri || !$salmonuri) { - // Get the canonical feed URI and check it - $discover = new FeedDiscovery(); - $feeduri = $discover->discoverFromURL($homeuri); - + if (array_key_exists('hub', $hints)) { + $huburi = $hints['hub']; + } else { + if (!$discover) { + $discover = new FeedDiscovery(); + $discover->discoverFromFeedURL($hints['feedurl']); + } $huburi = $discover->getAtomLink('hub'); - $salmonuri = $discover->getAtomLink('salmon'); + } - if (!$huburi) { - // We can only deal with folks with a PuSH hub - throw new FeedSubNoHubException(); - } + if (!$huburi) { + // We can only deal with folks with a PuSH hub + throw new FeedSubNoHubException(); } $oprofile = new Ostatus_profile(); -- cgit v1.2.3-54-g00ecf