From 6b8db5ad1333e2b430da3a771d9a962d44d4b6fc Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 5 Jan 2020 17:50:33 -0500 Subject: [PATCH] Update the Introductions domain to use repository, model and collection --- mod/notifications.php | 6 +- src/Collection/Introductions.php | 14 ++++ src/DI.php | 4 +- src/Factory/Mastodon/FollowRequest.php | 10 +-- src/Model/Introduction.php | 59 +++++++++------- src/Module/Api/Mastodon/FollowRequests.php | 81 +++++++++------------- src/Module/FollowConfirm.php | 6 +- src/Repository/Introduction.php | 30 ++++++++ 8 files changed, 124 insertions(+), 86 deletions(-) create mode 100644 src/Collection/Introductions.php create mode 100644 src/Repository/Introduction.php diff --git a/mod/notifications.php b/mod/notifications.php index 73730b50a5..420ac65a4d 100644 --- a/mod/notifications.php +++ b/mod/notifications.php @@ -31,14 +31,14 @@ function notifications_post(App $a) } if ($request_id) { - $Intro = DI::intro()->fetch(['id' => $request_id, 'uid' => local_user()]); + $intro = DI::intro()->selectFirst(['id' => $request_id, 'uid' => local_user()]); switch ($_POST['submit']) { case L10n::t('Discard'): - $Intro->discard(); + $intro->discard(); break; case L10n::t('Ignore'): - $Intro->ignore(); + $intro->ignore(); break; } diff --git a/src/Collection/Introductions.php b/src/Collection/Introductions.php new file mode 100644 index 0000000000..0d4e319cb7 --- /dev/null +++ b/src/Collection/Introductions.php @@ -0,0 +1,14 @@ + Factory\Mastodon\Relationship::class, 'cookie' => Model\User\Cookie::class, 'notify' => Model\Notify::class, - 'intro' => Model\Introduction::class, + 'intro' => Repository\Introduction::class, 'activity' => Protocol\Activity::class, 'aclFormatter' => Util\ACLFormatter::class, 'dtFormat' => Util\DateTimeFormat::class, diff --git a/src/Factory/Mastodon/FollowRequest.php b/src/Factory/Mastodon/FollowRequest.php index b59bfb8ae8..bbaa3135c9 100644 --- a/src/Factory/Mastodon/FollowRequest.php +++ b/src/Factory/Mastodon/FollowRequest.php @@ -23,17 +23,17 @@ class FollowRequest extends BaseFactory } /** - * @param Introduction $Introduction + * @param Introduction $introduction * @return \Friendica\Api\Entity\Mastodon\FollowRequest * @throws HTTPException\InternalServerErrorException * @throws \ImagickException */ - public function createFromIntroduction(Introduction $Introduction) + public function createFromIntroduction(Introduction $introduction) { - $cdata = Contact::getPublicAndUserContacID($Introduction->{'contact-id'}, $Introduction->uid); + $cdata = Contact::getPublicAndUserContacID($introduction->{'contact-id'}, $introduction->uid); if (empty($cdata)) { - $this->logger->warning('Wrong introduction data', ['Introduction' => $Introduction]); + $this->logger->warning('Wrong introduction data', ['Introduction' => $introduction]); throw new HTTPException\InternalServerErrorException('Wrong introduction data'); } @@ -42,6 +42,6 @@ class FollowRequest extends BaseFactory $apcontact = APContact::getByURL($publicContact['url'], false); - return new \Friendica\Api\Entity\Mastodon\FollowRequest($this->baseUrl, $Introduction->id, $publicContact, $apcontact, $userContact); + return new \Friendica\Api\Entity\Mastodon\FollowRequest($this->baseUrl, $introduction->id, $publicContact, $apcontact, $userContact); } } diff --git a/src/Model/Introduction.php b/src/Model/Introduction.php index 127765c0cb..ee4f0e71dc 100644 --- a/src/Model/Introduction.php +++ b/src/Model/Introduction.php @@ -4,10 +4,13 @@ namespace Friendica\Model; use Friendica\BaseModel; use Friendica\Core\Protocol; +use Friendica\Database\Database; use Friendica\Network\HTTPException; use Friendica\Protocol\ActivityPub; use Friendica\Protocol\Diaspora; +use Friendica\Repository; use Friendica\Util\DateTimeFormat; +use Psr\Log\LoggerInterface; /** * @property int uid @@ -20,33 +23,40 @@ use Friendica\Util\DateTimeFormat; * @property string datetime * @property bool blocked * @property bool ignored - * - * @package Friendica\Model */ final class Introduction extends BaseModel { - static $table_name = 'intro'; + /** @var Repository\Introduction */ + protected $intro; + + public function __construct(Database $dba, LoggerInterface $logger, Repository\Introduction $intro, array $data = []) + { + parent::__construct($dba, $logger, $data); + + $this->intro = $intro; + } /** - * Confirms a follow request and sends a notic to the remote contact. + * Confirms a follow request and sends a notice to the remote contact. * - * @param bool $duplex Is it a follow back? - * @param bool|null $hidden Should this contact be hidden? null = no change + * @param bool $duplex Is it a follow back? + * @param bool|null $hidden Should this contact be hidden? null = no change + * @return bool * @throws HTTPException\InternalServerErrorException - * @throws \ImagickException * @throws HTTPException\NotFoundException + * @throws \ImagickException */ public function confirm(bool $duplex = false, bool $hidden = null) { $this->logger->info('Confirming follower', ['cid' => $this->{'contact-id'}]); - $contact = Contact::selectFirst([], ['id' => $this->{'contact-id'}, 'uid' => $this->uid]); + $contact = Model\Contact::selectFirst([], ['id' => $this->{'contact-id'}, 'uid' => $this->uid]); if (!$contact) { throw new HTTPException\NotFoundException('Contact record not found.'); } - $new_relation = $contact['rel']; + $newRelation = $contact['rel']; $writable = $contact['writable']; if (!empty($contact['protocol'])) { @@ -61,12 +71,12 @@ final class Introduction extends BaseModel if (in_array($protocol, [Protocol::DIASPORA, Protocol::ACTIVITYPUB])) { if ($duplex) { - $new_relation = Contact::FRIEND; + $newRelation = Model\Contact::FRIEND; } else { - $new_relation = Contact::FOLLOWER; + $newRelation = Model\Contact::FOLLOWER; } - if ($new_relation != Contact::FOLLOWER) { + if ($newRelation != Model\Contact::FOLLOWER) { $writable = 1; } } @@ -79,43 +89,42 @@ final class Introduction extends BaseModel 'protocol' => $protocol, 'writable' => $writable, 'hidden' => $hidden ?? $contact['hidden'], - 'rel' => $new_relation, + 'rel' => $newRelation, ]; $this->dba->update('contact', $fields, ['id' => $contact['id']]); array_merge($contact, $fields); - if ($new_relation == Contact::FRIEND) { + if ($newRelation == Model\Contact::FRIEND) { if ($protocol == Protocol::DIASPORA) { - $ret = Diaspora::sendShare(User::getById($contact['uid']), $contact); + $ret = Diaspora::sendShare(Model\Contact::getById($contact['uid']), $contact); $this->logger->info('share returns', ['return' => $ret]); } elseif ($protocol == Protocol::ACTIVITYPUB) { ActivityPub\Transmitter::sendActivity('Follow', $contact['url'], $contact['uid']); } } - $this->delete(); + return $this->intro->delete($this); } /** * Silently ignores the introduction, hides it from notifications and prevents the remote contact from submitting * additional follow requests. * - * Chainable - * - * @return Introduction + * @return bool * @throws \Exception */ public function ignore() { - $this->dba->update('intro', ['ignore' => true], ['id' => $this->id]); + $this->ignored = true; - return $this; + return $this->intro->update($this); } /** * Discards the introduction and sends a rejection message to AP contacts. * + * @return bool * @throws HTTPException\InternalServerErrorException * @throws HTTPException\NotFoundException * @throws \ImagickException @@ -127,15 +136,15 @@ final class Introduction extends BaseModel if (!$this->fid) { // When the contact entry had been created just for that intro, we want to get rid of it now $condition = ['id' => $this->{'contact-id'}, 'uid' => $this->uid, - 'self' => false, 'pending' => true, 'rel' => [0, Contact::FOLLOWER]]; + 'self' => false, 'pending' => true, 'rel' => [0, Model\Contact::FOLLOWER]]; if ($this->dba->exists('contact', $condition)) { - Contact::remove($this->{'contact-id'}); + Model\Contact::remove($this->{'contact-id'}); } else { $this->dba->update('contact', ['pending' => false], ['id' => $this->{'contact-id'}]); } } - $contact = Contact::selectFirst([], ['id' => $this->{'contact-id'}, 'uid' => $this->uid]); + $contact = Model\Contact::selectFirst([], ['id' => $this->{'contact-id'}, 'uid' => $this->uid]); if (!$contact) { throw new HTTPException\NotFoundException('Contact record not found.'); @@ -151,6 +160,6 @@ final class Introduction extends BaseModel ActivityPub\Transmitter::sendContactReject($contact['url'], $contact['hub-verify'], $contact['uid']); } - $this->delete(); + return $this->intro->delete($this); } } diff --git a/src/Module/Api/Mastodon/FollowRequests.php b/src/Module/Api/Mastodon/FollowRequests.php index e31f023cde..fc384f7979 100644 --- a/src/Module/Api/Mastodon/FollowRequests.php +++ b/src/Module/Api/Mastodon/FollowRequests.php @@ -2,18 +2,16 @@ namespace Friendica\Module\Api\Mastodon; -use Friendica\Api\Mastodon; +use Friendica\Api\Entity\Mastodon; +use Friendica\Api\Entity\Mastodon\Relationship; use Friendica\Core\System; -use Friendica\Database\DBA; -use Friendica\Model\APContact; use Friendica\DI; use Friendica\Model\Contact; -use Friendica\Model\Introduction; use Friendica\Module\Base\Api; use Friendica\Network\HTTPException; /** - * @see https://docs.joinmastodon.org/api/rest/follow-requests/ + * @see https://docs.joinmastodon.org/methods/accounts/follow_requests */ class FollowRequests extends Api { @@ -30,8 +28,11 @@ class FollowRequests extends Api * @param array $parameters * @throws HTTPException\BadRequestException * @throws HTTPException\ForbiddenException + * @throws HTTPException\InternalServerErrorException * @throws HTTPException\NotFoundException * @throws HTTPException\UnauthorizedException + * @throws \ImagickException + * * @see https://docs.joinmastodon.org/methods/accounts/follow_requests#accept-follow * @see https://docs.joinmastodon.org/methods/accounts/follow_requests#reject-follow */ @@ -39,23 +40,25 @@ class FollowRequests extends Api { parent::post($parameters); - $Intro = DI::intro()->fetch(['id' => $parameters['id'], 'uid' => self::$current_user_id]); + $introduction = DI::intro()->selectFirst(['id' => $parameters['id'], 'uid' => self::$current_user_id]); - $contactId = $Intro->{'contact-id'}; - - $relationship = new Mastodon\Relationship(); - $relationship->id = $contactId; + $contactId = $introduction->{'contact-id'}; switch ($parameters['action']) { case 'authorize': - $Intro->confirm(); - $relationship = Mastodon\Relationship::createFromContact(Contact::getById($contactId)); + $introduction->confirm(); + + $relationship = DI::mstdnRelationship()->createFromContactId($contactId); break; case 'ignore': - $Intro->ignore(); + $introduction->ignore(); + + $relationship = DI::mstdnRelationship()->createDefaultFromContactId($contactId); break; case 'reject': - $Intro->discard(); + $introduction->discard(); + + $relationship = DI::mstdnRelationship()->createDefaultFromContactId($contactId); break; default: throw new HTTPException\BadRequestException('Unexpected action parameter, expecting "authorize", "ignore" or "reject"'); @@ -78,41 +81,23 @@ class FollowRequests extends Api $baseUrl = DI::baseUrl(); - if (isset($since_id) && isset($max_id)) { - $condition = ['`uid` = ? AND NOT `ignore` AND `id` > ? AND `id` < ?', self::$current_user_id, $since_id, $max_id]; - } elseif (isset($since_id)) { - $condition = ['`uid` = ? AND NOT `ignore` AND `id` > ?', self::$current_user_id, $since_id]; - } elseif (isset($max_id)) { - $condition = ['`uid` = ? AND NOT `ignore` AND `id` < ?', self::$current_user_id, $max_id]; - } else { - $condition = ['`uid` = ? AND NOT `ignore`', self::$current_user_id]; - } - - $count = DBA::count('intro', $condition); - - $intros = DBA::selectToArray( - 'intro', - [], - $condition, - ['order' => ['id' => 'DESC'], 'limit' => $limit] + $introductions = DI::intro()->selectByBoundaries( + ['`uid` = ? AND NOT `ignore`', self::$current_user_id], + ['order' => ['id' => 'DESC']], + $since_id, + $max_id, + $limit ); $return = []; - foreach ($intros as $intro) { - $cdata = Contact::getPublicAndUserContacID($intro['contact-id'], $intro['uid']); - if (empty($cdata['public'])) { - continue; + + foreach ($introductions as $key => $introduction) { + try { + $return[] = DI::mstdnFollowRequest()->createFromIntroduction($introduction); + } catch (HTTPException\InternalServerErrorException $exception) { + DI::intro()->delete($introduction); + unset($introductions[$key]); } - - $publicContact = Contact::getById($cdata['public']); - $userContact = Contact::getById($cdata['user']); - $apcontact = APContact::getByURL($publicContact['url'], false); - $account = Mastodon\Account::create($baseUrl, $publicContact, $apcontact, $userContact); - - // Not ideal, the same "account" can have multiple ids depending on the context - $account->id = $intro['id']; - - $return[] = $account; } $base_query = []; @@ -121,10 +106,10 @@ class FollowRequests extends Api } $links = []; - if ($count > $limit) { - $links[] = '<' . $baseUrl->get() . '/api/v1/follow_requests?' . http_build_query($base_query + ['max_id' => $intros[count($intros) - 1]['id']]) . '>; rel="next"'; + if ($introductions->getTotalCount() > $limit) { + $links[] = '<' . $baseUrl->get() . '/api/v1/follow_requests?' . http_build_query($base_query + ['max_id' => $introductions[count($introductions) - 1]->id]) . '>; rel="next"'; } - $links[] = '<' . $baseUrl->get() . '/api/v1/follow_requests?' . http_build_query($base_query + ['since_id' => $intros[0]['id']]) . '>; rel="prev"'; + $links[] = '<' . $baseUrl->get() . '/api/v1/follow_requests?' . http_build_query($base_query + ['since_id' => $introductions[0]->id]) . '>; rel="prev"'; header('Link: ' . implode(', ', $links)); diff --git a/src/Module/FollowConfirm.php b/src/Module/FollowConfirm.php index e54032c850..2da2685b6d 100644 --- a/src/Module/FollowConfirm.php +++ b/src/Module/FollowConfirm.php @@ -23,11 +23,11 @@ class FollowConfirm extends BaseModule $duplex = intval($_POST['duplex'] ?? 0); $hidden = intval($_POST['hidden'] ?? 0); - $Intro = DI::intro()->fetch(['id' => $intro_id, 'uid' => local_user()]); + $intro = DI::intro()->selectFirst(['id' => $intro_id, 'uid' => local_user()]); - $cid = $Intro->{'contact-id'}; + $cid = $intro->{'contact-id'}; - $Intro->confirm($duplex, $hidden); + $intro->confirm($duplex, $hidden); DI::baseUrl()->redirect('contact/' . intval($cid)); } diff --git a/src/Repository/Introduction.php b/src/Repository/Introduction.php new file mode 100644 index 0000000000..03d3e59aeb --- /dev/null +++ b/src/Repository/Introduction.php @@ -0,0 +1,30 @@ +dba, $this->logger, $this, $data); + } +}