From 378a43d23e8599587bab32718a0953adf5d2dadd Mon Sep 17 00:00:00 2001 From: Maxence Lange Date: Fri, 30 Nov 2018 09:56:54 -0100 Subject: [PATCH] left join follow in search Signed-off-by: Maxence Lange --- lib/Controller/LocalController.php | 13 ++++++ lib/Db/CacheActorsRequest.php | 55 +++++++++++++++++++++-- lib/Db/CoreRequestBuilder.php | 72 +++++++++++++++++++++++++++++- 3 files changed, 134 insertions(+), 6 deletions(-) diff --git a/lib/Controller/LocalController.php b/lib/Controller/LocalController.php index eab56caa..73a05cec 100644 --- a/lib/Controller/LocalController.php +++ b/lib/Controller/LocalController.php @@ -294,12 +294,22 @@ class LocalController extends Controller { * @param string $search * * @return DataResponse + * @throws Exception */ public function accountsSearch(string $search): DataResponse { + try { + $viewer = $this->actorService->getActorFromUserId($this->userId, true); + } catch (Exception $e) { + throw new Exception(); + } + + $this->personService->setViewerId($viewer->getId()); + /* Look for an exactly matching account */ $match = null; try { $match = $this->personService->getFromAccount($search, false); + $match->setCompleteDetails(true); } catch (Exception $e) { } @@ -410,6 +420,7 @@ class LocalController extends Controller { * @NoCSRFRequired * @NoAdminRequired * @NoSubAdminRequired + * * @param string $id * @return DataResponse */ @@ -419,8 +430,10 @@ class LocalController extends Controller { if ($actor->gotIcon()) { $avatar = $actor->getIcon(); $document = $this->documentService->getFromCache($avatar->getId()); + return new FileDisplayResponse($document); } + return new NotFoundResponse(); } catch (Exception $e) { return $this->fail($e); diff --git a/lib/Db/CacheActorsRequest.php b/lib/Db/CacheActorsRequest.php index 7887ad12..b882f9d7 100644 --- a/lib/Db/CacheActorsRequest.php +++ b/lib/Db/CacheActorsRequest.php @@ -33,6 +33,7 @@ namespace OCA\Social\Db; use DateTime; use Exception; use OCA\Social\Exceptions\CacheActorDoesNotExistException; +use OCA\Social\Exceptions\InvalidResourceException; use OCA\Social\Model\ActivityPub\Person; use OCA\Social\Service\ConfigService; use OCA\Social\Service\MiscService; @@ -133,14 +134,21 @@ class CacheActorsRequest extends CacheActorsRequestBuilder { * * @param string $account * + * @param string $viewerId + * * @return Person * @throws CacheActorDoesNotExistException */ - public function getFromAccount(string $account): Person { + public function getFromAccount(string $account, string $viewerId = ''): Person { $qb = $this->getCacheActorsSelectSql(); $this->limitToAccount($qb, $account); $this->leftJoinCacheDocuments($qb, 'icon_id'); + if ($viewerId !== '') { + $this->leftJoinFollowAsViewer($qb, 'id', $viewerId, true, 'as_follower'); + $this->leftJoinFollowAsViewer($qb, 'id', $viewerId, false, 'as_followed'); + } + $cursor = $qb->execute(); $data = $cursor->fetch(); $cursor->closeCursor(); @@ -149,7 +157,21 @@ class CacheActorsRequest extends CacheActorsRequestBuilder { throw new CacheActorDoesNotExistException(); } - return $this->parseCacheActorsSelectSql($data); + $account = $this->parseCacheActorsSelectSql($data); + + try { + $this->parseFollowLeftJoin($data, 'as_follower'); + $account->addDetailBool('follower', true); + } catch (InvalidResourceException $e) { + } + + try { + $this->parseFollowLeftJoin($data, 'as_following'); + $account->addDetailBool('following', true); + } catch (InvalidResourceException $e) { + } + + return $account; } @@ -181,18 +203,43 @@ class CacheActorsRequest extends CacheActorsRequestBuilder { /** * @param string $search + * @param string $viewerId * * @return Person[] */ - public function searchAccounts(string $search): array { + public function searchAccounts(string $search, string $viewerId = ''): array { $qb = $this->getCacheActorsSelectSql(); $this->searchInAccount($qb, $search); $this->leftJoinCacheDocuments($qb, 'icon_id'); + if ($viewerId !== '') { + $this->leftJoinFollowAsViewer($qb, 'id', $viewerId, true, 'as_follower'); + $this->leftJoinFollowAsViewer($qb, 'id', $viewerId, false, 'as_followed'); + } + + $accounts = []; $cursor = $qb->execute(); while ($data = $cursor->fetch()) { - $accounts[] = $this->parseCacheActorsSelectSql($data); + $account = $this->parseCacheActorsSelectSql($data); + + if ($viewerId !== '') { + try { + $this->parseFollowLeftJoin($data, 'as_follower'); + $account->addDetailBool('following', true); + } catch (InvalidResourceException $e) { + } + + try { + $this->parseFollowLeftJoin($data, 'as_followed'); + $account->addDetailBool('follower', true); + } catch (InvalidResourceException $e) { + } + + $account->setCompleteDetails(true); + } + + $accounts[] = $account; } $cursor->closeCursor(); diff --git a/lib/Db/CoreRequestBuilder.php b/lib/Db/CoreRequestBuilder.php index 130dedd7..114dc671 100644 --- a/lib/Db/CoreRequestBuilder.php +++ b/lib/Db/CoreRequestBuilder.php @@ -37,6 +37,7 @@ use Doctrine\DBAL\Query\QueryBuilder; use Exception; use OCA\Social\Exceptions\InvalidResourceException; use OCA\Social\Model\ActivityPub\Document; +use OCA\Social\Model\ActivityPub\Follow; use OCA\Social\Model\ActivityPub\Image; use OCA\Social\Model\ActivityPub\Person; use OCA\Social\Service\ConfigService; @@ -530,7 +531,6 @@ class CoreRequestBuilder { $expr = $qb->expr(); $pf = $this->defaultSelectAlias; -// /** @noinspection PhpMethodParametersCountMismatchInspection */ $qb->selectAlias('ca.id', 'cacheactor_id') ->selectAlias('ca.type', 'cacheactor_type') ->selectAlias('ca.account', 'cacheactor_account') @@ -592,7 +592,6 @@ class CoreRequestBuilder { $expr = $qb->expr(); $pf = $this->defaultSelectAlias; -// /** @noinspection PhpMethodParametersCountMismatchInspection */ $qb->selectAlias('cd.id', 'cachedocument_id') ->selectAlias('cd.type', 'cachedocument_type') ->selectAlias('cd.mime_type', 'cachedocument_mime_type') @@ -635,6 +634,75 @@ class CoreRequestBuilder { return $document; } + + /** + * @param IQueryBuilder $qb + * @param string $fieldActorId + * @param string $viewerId + * @param bool $asFollower + * @param string $prefix + */ + protected function leftJoinFollowAsViewer( + IQueryBuilder &$qb, string $fieldActorId, string $viewerId, bool $asFollower = true, + string $prefix = 'follow' + ) { + if ($qb->getType() !== QueryBuilder::SELECT) { + return; + } + + $expr = $qb->expr(); + $pf = $this->defaultSelectAlias; + + $andX = $expr->andX(); + if ($asFollower === true) { + $andX->add($expr->eq($pf . '.' . $fieldActorId, $prefix . '_f.object_id')); + $andX->add($expr->eq($prefix . '_f.actor_id', $qb->createNamedParameter($viewerId))); + } else { + $andX->add($expr->eq($pf . '.' . $fieldActorId, $prefix . '_f.actor_id')); + $andX->add($expr->eq($prefix . '_f.object_id', $qb->createNamedParameter($viewerId))); + } + + $qb->selectAlias($prefix . '_f.id', $prefix . '_id') + ->selectAlias($prefix . '_f.type', $prefix . '_type') + ->selectAlias($prefix . '_f.actor_id', $prefix . '_actor_id') + ->selectAlias($prefix . '_f.object_id', $prefix . '_object_id') + ->selectAlias($prefix . '_f.follow_id', $prefix . '_follow_id') + ->selectAlias($prefix . '_f.creation', $prefix . '_creation') + ->leftJoin( + $this->defaultSelectAlias, CoreRequestBuilder::TABLE_SERVER_FOLLOWS, $prefix . '_f', + $andX + ); + } + + + /** + * @param array $data + * @param string $prefix + * + * @return Follow + * @throws InvalidResourceException + */ + protected function parseFollowLeftJoin(array $data, string $prefix): Follow { + $new = []; + + $length = strlen($prefix) + 1; + foreach ($data as $k => $v) { + if (substr($k, 0, $length) === $prefix . '_') { + $new[substr($k, $length)] = $v; + } + } + + $follow = new Follow(); + $follow->importFromDatabase($new); + + if ($follow->getType() !== Follow::TYPE) { + throw new InvalidResourceException(); + } + + return $follow; + } + + }