From 25447c2527f5e26e4094e1a2598227836698b6f2 Mon Sep 17 00:00:00 2001 From: Hannes Mannerheim Date: Wed, 18 Nov 2015 15:32:20 +0100 Subject: [PATCH] API for getting a profile's blocked profiles --- QvitterPlugin.php | 2 + actions/apiqvitterblocks.php | 188 +++++++++++++++++++++++++++++++++++ classes/QvitterBlocked.php | 112 +++++++++++++++++++++ 3 files changed, 302 insertions(+) create mode 100644 actions/apiqvitterblocks.php create mode 100644 classes/QvitterBlocked.php diff --git a/QvitterPlugin.php b/QvitterPlugin.php index 7b2278a..b9384bf 100644 --- a/QvitterPlugin.php +++ b/QvitterPlugin.php @@ -141,6 +141,8 @@ class QvitterPlugin extends Plugin { public function onRouterInitialized($m) { + $m->connect('api/qvitter/blocks.json', + array('action' => 'ApiQvitterBlocks')); $m->connect('api/qvitter/hello.json', array('action' => 'ApiQvitterHello')); $m->connect('api/qvitter/mark_all_notifications_as_seen.json', diff --git a/actions/apiqvitterblocks.php b/actions/apiqvitterblocks.php new file mode 100644 index 0000000..8cfa735 --- /dev/null +++ b/actions/apiqvitterblocks.php @@ -0,0 +1,188 @@ + \\\\_\ · + · \\) \____) · + · · + · · + · · + · Qvitter is free software: you can redistribute it and / or modify it · + · under the terms of the GNU Affero General Public License as published by · + · the Free Software Foundation, either version three of the License or (at · + · your option) any later version. · + · · + · Qvitter is distributed in hope that it will be useful but WITHOUT ANY · + · WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS · + · FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for · + · more details. · + · · + · You should have received a copy of the GNU Affero General Public License · + · along with Qvitter. If not, see . · + · · + · Contact h@nnesmannerhe.im if you have any questions. · + · · + · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */ + +if (!defined('STATUSNET')) { + exit(1); +} + + +class ApiQvitterBlocksAction extends ApiBareAuthAction +{ + var $profiles = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + */ + protected function prepare(array $args=array()) + { + parent::prepare($args); + + // If called as a social graph method, show 5000 per page, otherwise 100 + + $this->count = (int)$this->arg('count', 100); + + $this->target = $this->getTargetProfile($this->arg('id')); + + if (!($this->target instanceof Profile)) { + // TRANS: Client error displayed when requesting a list of followers for a non-existing user. + $this->clientError(_('No such user.'), 404); + } + + $this->profiles = $this->getProfiles(); + + return true; + } + + /** + * Handle the request + * + * Show the profiles + * + * @return void + */ + protected function handle() + { + parent::handle(); + + $this->initDocument('json'); + print json_encode($this->showProfiles()); + $this->endDocument('json'); + } + + /** + * Get the user's subscribers (followers) as an array of profiles + * + * @return array Profiles + */ + protected function getProfiles() + { + $offset = ($this->page - 1) * $this->count; + $limit = $this->count + 1; + + $blocks = null; + + $blocks = QvitterBlocked::getBlocked($this->target->id, $offset, $limit); + + $profiles = array(); + + while ($blocks->fetch()) { + $this_profile_block = clone($blocks); + $profiles[] = $this->getTargetProfile($this_profile_block->blocked); + } + + return $profiles; + } + + /** + * Is this action read only? + * + * @param array $args other arguments + * + * @return boolean true + */ + function isReadOnly($args) + { + return true; + } + + /** + * When was this feed last modified? + * + * @return string datestamp of the latest profile in the stream + */ + function lastModified() + { + if (!empty($this->profiles) && (count($this->profiles) > 0)) { + return strtotime($this->profiles[0]->modified); + } + + return null; + } + + /** + * An entity tag for this action + * + * Returns an Etag based on the action name, language, user ID, and + * timestamps of the first and last profiles in the subscriptions list + * There's also an indicator to show whether this action is being called + * as /api/statuses/(friends|followers) or /api/(friends|followers)/ids + * + * @return string etag + */ + function etag() + { + if (!empty($this->profiles) && (count($this->profiles) > 0)) { + + $last = count($this->profiles) - 1; + + return '"' . implode( + ':', + array($this->arg('action'), + common_user_cache_hash($this->auth_user), + common_language(), + $this->target->id, + 'Profiles', + strtotime($this->profiles[0]->modified), + strtotime($this->profiles[$last]->modified)) + ) + . '"'; + } + + return null; + } + + /** + * Show the profiles as Twitter-style useres and statuses + * + * @return void + */ + function showProfiles() + { + $user_arrays = array(); + foreach ($this->profiles as $profile) { + $user_arrays[] = $this->twitterUserArray($profile, false ); + } + return $user_arrays; + } +} diff --git a/classes/QvitterBlocked.php b/classes/QvitterBlocked.php new file mode 100644 index 0000000..0affb1c --- /dev/null +++ b/classes/QvitterBlocked.php @@ -0,0 +1,112 @@ + \\\\_\ · + · \\) \____) · + · · + · · + · · + · Qvitter is free software: you can redistribute it and / or modify it · + · under the terms of the GNU Affero General Public License as published by · + · the Free Software Foundation, either version three of the License or (at · + · your option) any later version. · + · · + · Qvitter is distributed in hope that it will be useful but WITHOUT ANY · + · WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS · + · FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for · + · more details. · + · · + · You should have received a copy of the GNU Affero General Public License · + · along with Qvitter. If not, see . · + · · + · Contact h@nnesmannerhe.im if you have any questions. · + · · + · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */ + + +if (!defined('GNUSOCIAL')) { exit(1); } + +class QvitterBlocked extends Profile_block +{ + + const CACHE_WINDOW = 201; + + public static function getBlocked($profile_id, $offset = 0, $limit = PROFILES_PER_PAGE) + { + $ids = self::getBlockedIDs($profile_id, $offset, $limit); + return Profile_block::listFind('blocked', $ids); + } + + + private static function getBlockedIDs($profile_id, $offset, $limit) + { + $cacheKey = 'qvitterblocked:'.$profile_id; + + $queryoffset = $offset; + $querylimit = $limit; + + if ($offset + $limit <= self::CACHE_WINDOW) { + // Oh, it seems it should be cached + $ids = self::cacheGet($cacheKey); + if (is_array($ids)) { + return array_slice($ids, $offset, $limit); + } + // Being here indicates we didn't find anything cached + // so we'll have to fill it up simultaneously + $queryoffset = 0; + $querylimit = self::CACHE_WINDOW; + } + + $blocks = new Profile_block(); + $blocks->blocker = $profile_id; + $blocks->selectAdd('blocked'); + $blocks->whereAdd("blocked != {$profile_id}"); + $blocks->orderBy('modified DESC'); + $blocks->limit($queryoffset, $querylimit); + + if (!$blocks->find()) { + return array(); + } + + $ids = $blocks->fetchAll('blocked'); + + // If we're simultaneously filling up cache, remember to slice + if ($queryoffset === 0 && $querylimit === self::CACHE_WINDOW) { + self::cacheSet($cacheKey, $ids); + return array_slice($ids, $offset, $limit); + } + + return $ids; + } + + /** + * Flush cached blocks when blocks are updated + * + * @param mixed $dataObject Original version of object + * + * @return boolean success flag. + */ + function update($dataObject=false) + { + self::blow('qvitterblocked:'.$this->blocker); + self::blow('qvitterblocked:'.$this->blocked); + + return parent::update($dataObject); + } + +}