X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=lib%2Fapiaction.php;h=8c1b4c67e7081bfa211931c92c9f5b77ce31f3f7;hb=52de57e2f6aacd1d5f89d4e1617e8a52af598680;hp=64b4284f6aa1e2eb4e57ddc00efa3e0e88ea7d2b;hpb=8884a5255fb90fda67b63fa0d4252d77176337e5;p=quix0rs-gnu-social.git diff --git a/lib/apiaction.php b/lib/apiaction.php index 64b4284f6a..8c1b4c67e7 100644 --- a/lib/apiaction.php +++ b/lib/apiaction.php @@ -54,7 +54,7 @@ @subsection usermethods_sec User Methods - @subsection directmessagemethods_sec Direct Message Methods + @subsection directmessagemethods_sec Direct Message Methods (now a plugin) @subsection friendshipmethods_sec Friendship Methods @@ -119,15 +119,17 @@ class ApiAction extends Action const READ_ONLY = 1; const READ_WRITE = 2; - var $format = null; var $user = null; var $auth_user = null; var $page = null; var $count = null; + var $offset = null; + var $limit = null; var $max_id = null; var $since_id = null; var $source = null; var $callback = null; + var $format = null; var $access = self::READ_ONLY; // read (default) or read-write @@ -140,9 +142,9 @@ class ApiAction extends Action * * @return boolean false if user doesn't exist */ - function prepare($args) + protected function prepare(array $args=array()) { - StatusNet::setApi(true); // reduce exception reports to aid in debugging + GNUsocial::setApi(true); // reduce exception reports to aid in debugging parent::prepare($args); $this->format = $this->arg('format'); @@ -152,8 +154,12 @@ class ApiAction extends Action $this->max_id = (int)$this->arg('max_id', 0); $this->since_id = (int)$this->arg('since_id', 0); + // These two are not used everywhere, mainly just AtompubAction extensions + $this->offset = ($this->page-1) * $this->count; + $this->limit = $this->count + 1; + if ($this->arg('since')) { - header('X-StatusNet-Warning: since parameter is disabled; use since_id'); + header('X-GNUsocial-Warning: since parameter is disabled; use since_id'); } $this->source = $this->trimmed('source'); @@ -172,10 +178,10 @@ class ApiAction extends Action * * @return void */ - function handle($args) + protected function handle() { header('Access-Control-Allow-Origin: *'); - parent::handle($args); + parent::handle(); } /** @@ -202,7 +208,11 @@ class ApiAction extends Action { $twitter_user = array(); - $user = $profile->getUser(); + try { + $user = $profile->getUser(); + } catch (NoSuchUserException $e) { + $user = null; + } $twitter_user['id'] = intval($profile->id); $twitter_user['name'] = $profile->getBestName(); @@ -210,21 +220,35 @@ class ApiAction extends Action $twitter_user['location'] = ($profile->location) ? $profile->location : null; $twitter_user['description'] = ($profile->bio) ? $profile->bio : null; - $avatar = $profile->getAvatar(AVATAR_STREAM_SIZE); - $twitter_user['profile_image_url'] = ($avatar) ? $avatar->displayUrl() : - Avatar::defaultImage(AVATAR_STREAM_SIZE); + // TODO: avatar url template (example.com/user/avatar?size={x}x{y}) + $twitter_user['profile_image_url'] = Avatar::urlByProfile($profile, AVATAR_STREAM_SIZE); + $twitter_user['profile_image_url_https'] = $twitter_user['profile_image_url']; + + // START introduced by qvitter API, not necessary for StatusNet API + $twitter_user['profile_image_url_profile_size'] = Avatar::urlByProfile($profile, AVATAR_PROFILE_SIZE); + try { + $avatar = Avatar::getUploaded($profile); + $origurl = $avatar->displayUrl(); + } catch (Exception $e) { + $origurl = $twitter_user['profile_image_url_profile_size']; + } + $twitter_user['profile_image_url_original'] = $origurl; + + $twitter_user['groups_count'] = $profile->getGroupCount(); + foreach (array('linkcolor', 'backgroundcolor') as $key) { + $twitter_user[$key] = Profile_prefs::getConfigData($profile, 'theme', $key); + } + // END introduced by qvitter API, not necessary for StatusNet API $twitter_user['url'] = ($profile->homepage) ? $profile->homepage : null; - $twitter_user['protected'] = ($user->private_stream) ? true : false; + $twitter_user['protected'] = (!empty($user) && $user->private_stream) ? true : false; $twitter_user['followers_count'] = $profile->subscriberCount(); // Note: some profiles don't have an associated user $twitter_user['friends_count'] = $profile->subscriptionCount(); - $twitter_user['created_at'] = $this->dateTwitter($profile->created); - - $twitter_user['favourites_count'] = $profile->faveCount(); // British spelling! + $twitter_user['created_at'] = self::dateTwitter($profile->created); $timezone = 'UTC'; @@ -240,28 +264,26 @@ class ApiAction extends Action $twitter_user['statuses_count'] = $profile->noticeCount(); // Is the requesting user following this user? + // These values might actually also mean "unknown". Ambiguity issues? $twitter_user['following'] = false; - $twitter_user['statusnet:blocking'] = false; + $twitter_user['statusnet_blocking'] = false; $twitter_user['notifications'] = false; - if (isset($this->auth_user)) { - - $twitter_user['following'] = $this->auth_user->isSubscribed($profile); - $twitter_user['statusnet:blocking'] = $this->auth_user->hasBlocked($profile); - - // Notifications on? - $sub = Subscription::pkeyGet(array('subscriber' => - $this->auth_user->id, - 'subscribed' => $profile->id)); - - if ($sub) { + if ($this->scoped instanceof Profile) { + try { + $sub = Subscription::getSubscription($this->scoped, $profile); + // Notifications on? + $twitter_user['following'] = true; + $twitter_user['statusnet_blocking'] = $this->scoped->hasBlocked($profile); $twitter_user['notifications'] = ($sub->jabber || $sub->sms); + } catch (NoResultException $e) { + // well, the values are already false... } } if ($get_notice) { $notice = $profile->getCurrentNotice(); - if ($notice) { + if ($notice instanceof Notice) { // don't get user! $twitter_user['status'] = $this->twitterStatusArray($notice, false); } @@ -271,6 +293,9 @@ class ApiAction extends Action $twitter_user['statusnet_profile_url'] = $profile->profileurl; + // The event call to handle NoticeSimpleStatusArray lets plugins add data to the output array + Event::handle('TwitterUserArray', array($profile, &$twitter_user, $this->scoped, array())); + return $twitter_user; } @@ -278,11 +303,12 @@ class ApiAction extends Action { $base = $this->twitterSimpleStatusArray($notice, $include_user); + // FIXME: MOVE TO SHARE PLUGIN if (!empty($notice->repeat_of)) { - $original = Notice::staticGet('id', $notice->repeat_of); - if (!empty($original)) { - $original_array = $this->twitterSimpleStatusArray($original, $include_user); - $base['retweeted_status'] = $original_array; + $original = Notice::getKV('id', $notice->repeat_of); + if ($original instanceof Notice) { + $orig_array = $this->twitterSimpleStatusArray($original, $include_user); + $base['retweeted_status'] = $orig_array; } } @@ -296,14 +322,21 @@ class ApiAction extends Action $twitter_status = array(); $twitter_status['text'] = $notice->content; $twitter_status['truncated'] = false; # Not possible on StatusNet - $twitter_status['created_at'] = $this->dateTwitter($notice->created); - $twitter_status['in_reply_to_status_id'] = ($notice->reply_to) ? - intval($notice->reply_to) : null; + $twitter_status['created_at'] = self::dateTwitter($notice->created); + try { + // We could just do $notice->reply_to but maybe the future holds a + // different story for parenting. + $parent = $notice->getParent(); + $in_reply_to = $parent->id; + } catch (NoParentNoticeException $e) { + $in_reply_to = null; + } + $twitter_status['in_reply_to_status_id'] = $in_reply_to; $source = null; $ns = $notice->getSource(); - if ($ns) { + if ($ns instanceof Notice_source) { if (!empty($ns->name) && !empty($ns->url)) { $source = 'getBestName(); - $entry['author-uri'] = $from->homepage; - - $avatar = $from->getAvatar(AVATAR_STREAM_SIZE); - - $entry['avatar'] = (!empty($avatar)) ? $avatar->url : Avatar::defaultImage(AVATAR_STREAM_SIZE); - $entry['avatar-type'] = (!empty($avatar)) ? $avatar->mediatype : 'image/png'; - - // RSS item specific - - $entry['description'] = $entry['content']; - $entry['pubDate'] = common_date_rfc2822($message->created); - $entry['guid'] = $entry['link']; - - return $entry; - } - - function showSingleXmlDirectMessage($message) - { - $this->initDocument('xml'); - $dmsg = $this->directMessageArray($message); - $this->showXmlDirectMessage($dmsg, true); - $this->endDocument('xml'); - } - - function showSingleJsonDirectMessage($message) - { - $this->initDocument('json'); - $dmsg = $this->directMessageArray($message); - $this->showJsonObjects($dmsg); - $this->endDocument('json'); - } - function showAtomGroups($group, $title, $id, $link, $subtitle=null, $selfuri=null) { $this->initDocument('atom'); @@ -1057,7 +1017,13 @@ class ApiAction extends Action $statuses = array(); if (is_array($notice)) { - $notice = new ArrayWrapper($notice); + //FIXME: make everything calling showJsonTimeline use only Notice objects + common_debug('ArrayWrapper avoidance in progress! Beep boop, make showJsonTimeline only receive Notice objects!'); + $ids = array(); + foreach ($notice as $n) { + $ids[] = $n->getID(); + } + $notice = Notice::multiGet('id', $ids); } while ($notice->fetch()) { @@ -1256,7 +1222,7 @@ class ApiAction extends Action $this->endDocument('xml'); } - function dateTwitter($dt) + static function dateTwitter($dt) { $dateStr = date('d F Y H:i:s', strtotime($dt)); $d = new DateTime($dateStr, new DateTimeZone('UTC')); @@ -1290,7 +1256,6 @@ class ApiAction extends Action default: // TRANS: Client error on an API request with an unsupported data format. $this->clientError(_('Not a supported data format.')); - break; } return; @@ -1317,91 +1282,10 @@ class ApiAction extends Action default: // TRANS: Client error on an API request with an unsupported data format. $this->clientError(_('Not a supported data format.')); - break; } return; } - function clientError($msg, $code = 400, $format = null) - { - $action = $this->trimmed('action'); - if ($format === null) { - $format = $this->format; - } - - common_debug("User error '$code' on '$action': $msg", __FILE__); - - if (!array_key_exists($code, ClientErrorAction::$status)) { - $code = 400; - } - - $status_string = ClientErrorAction::$status[$code]; - - // Do not emit error header for JSONP - if (!isset($this->callback)) { - header('HTTP/1.1 ' . $code . ' ' . $status_string); - } - - switch($format) { - case 'xml': - $this->initDocument('xml'); - $this->elementStart('hash'); - $this->element('error', null, $msg); - $this->element('request', null, $_SERVER['REQUEST_URI']); - $this->elementEnd('hash'); - $this->endDocument('xml'); - break; - case 'json': - $this->initDocument('json'); - $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']); - print(json_encode($error_array)); - $this->endDocument('json'); - break; - case 'text': - header('Content-Type: text/plain; charset=utf-8'); - print $msg; - break; - default: - // If user didn't request a useful format, throw a regular client error - throw new ClientException($msg, $code); - } - } - - function serverError($msg, $code = 500, $content_type = null) - { - $action = $this->trimmed('action'); - if ($content_type === null) { - $content_type = $this->format; - } - - common_debug("Server error '$code' on '$action': $msg", __FILE__); - - if (!array_key_exists($code, ServerErrorAction::$status)) { - $code = 400; - } - - $status_string = ServerErrorAction::$status[$code]; - - // Do not emit error header for JSONP - if (!isset($this->callback)) { - header('HTTP/1.1 '.$code.' '.$status_string); - } - - if ($content_type == 'xml') { - $this->initDocument('xml'); - $this->elementStart('hash'); - $this->element('error', null, $msg); - $this->element('request', null, $_SERVER['REQUEST_URI']); - $this->elementEnd('hash'); - $this->endDocument('xml'); - } else { - $this->initDocument('json'); - $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']); - print(json_encode($error_array)); - $this->endDocument('json'); - } - } - function initTwitterRss() { $this->startXML(); @@ -1452,7 +1336,6 @@ class ApiAction extends Action default: // TRANS: Client error on an API request with an unsupported data format. $this->clientError(_('Not a supported data format.')); - return; } return; } @@ -1467,29 +1350,29 @@ class ApiAction extends Action if (empty($id)) { // Twitter supports these other ways of passing the user ID if (self::is_decimal($this->arg('id'))) { - return User::staticGet($this->arg('id')); + return User::getKV($this->arg('id')); } else if ($this->arg('id')) { $nickname = common_canonical_nickname($this->arg('id')); - return User::staticGet('nickname', $nickname); + return User::getKV('nickname', $nickname); } else if ($this->arg('user_id')) { // This is to ensure that a non-numeric user_id still // overrides screen_name even if it doesn't get used if (self::is_decimal($this->arg('user_id'))) { - return User::staticGet('id', $this->arg('user_id')); + return User::getKV('id', $this->arg('user_id')); } } else if ($this->arg('screen_name')) { $nickname = common_canonical_nickname($this->arg('screen_name')); - return User::staticGet('nickname', $nickname); + return User::getKV('nickname', $nickname); } else { // Fall back to trying the currently authenticated user - return $this->auth_user; + return $this->scoped->getUser(); } } else if (self::is_decimal($id)) { - return User::staticGet($id); + return User::getKV($id); } else { $nickname = common_canonical_nickname($id); - return User::staticGet('nickname', $nickname); + return User::getKV('nickname', $nickname); } } @@ -1499,28 +1382,31 @@ class ApiAction extends Action // Twitter supports these other ways of passing the user ID if (self::is_decimal($this->arg('id'))) { - return Profile::staticGet($this->arg('id')); + return Profile::getKV($this->arg('id')); } else if ($this->arg('id')) { // Screen names currently can only uniquely identify a local user. $nickname = common_canonical_nickname($this->arg('id')); - $user = User::staticGet('nickname', $nickname); + $user = User::getKV('nickname', $nickname); return $user ? $user->getProfile() : null; } else if ($this->arg('user_id')) { // This is to ensure that a non-numeric user_id still // overrides screen_name even if it doesn't get used if (self::is_decimal($this->arg('user_id'))) { - return Profile::staticGet('id', $this->arg('user_id')); + return Profile::getKV('id', $this->arg('user_id')); } } else if ($this->arg('screen_name')) { $nickname = common_canonical_nickname($this->arg('screen_name')); - $user = User::staticGet('nickname', $nickname); - return $user ? $user->getProfile() : null; + $user = User::getKV('nickname', $nickname); + return $user instanceof User ? $user->getProfile() : null; + } else { + // Fall back to trying the currently authenticated user + return $this->scoped; } } else if (self::is_decimal($id)) { - return Profile::staticGet($id); + return Profile::getKV($id); } else { $nickname = common_canonical_nickname($id); - $user = User::staticGet('nickname', $nickname); + $user = User::getKV('nickname', $nickname); return $user ? $user->getProfile() : null; } } @@ -1529,21 +1415,23 @@ class ApiAction extends Action { if (empty($id)) { if (self::is_decimal($this->arg('id'))) { - return User_group::staticGet('id', $this->arg('id')); + return User_group::getKV('id', $this->arg('id')); } else if ($this->arg('id')) { return User_group::getForNickname($this->arg('id')); } else if ($this->arg('group_id')) { // This is to ensure that a non-numeric group_id still // overrides group_name even if it doesn't get used if (self::is_decimal($this->arg('group_id'))) { - return User_group::staticGet('id', $this->arg('group_id')); + return User_group::getKV('id', $this->arg('group_id')); } } else if ($this->arg('group_name')) { return User_group::getForNickname($this->arg('group_name')); } } else if (self::is_decimal($id)) { - return User_group::staticGet('id', $id); + return User_group::getKV('id', $id); + } else if ($this->arg('uri')) { // FIXME: move this into empty($id) check? + return User_group::getKV('uri', urldecode($this->arg('uri'))); } else { return User_group::getForNickname($id); } @@ -1560,7 +1448,7 @@ class ApiAction extends Action if($id) { if (is_numeric($id)) { - $list = Profile_list::staticGet('id', $id); + $list = Profile_list::getKV('id', $id); // only if the list with the id belongs to the tagger if(empty($list) || $list->tagger != $tagger->id) { @@ -1573,7 +1461,7 @@ class ApiAction extends Action } if (!empty($list) && $list->private) { - if ($this->auth_user->id == $list->tagger) { + if ($this->scoped->id == $list->tagger) { return $list; } } else { @@ -1641,6 +1529,11 @@ class ApiAction extends Action $aargs['id'] = $id; } + $user = $this->arg('user'); + if (!empty($user)) { + $aargs['user'] = $user; + } + $tag = $this->arg('tag'); if (!empty($tag)) { $aargs['tag'] = $tag;