From: Philipp <admin@philipp.info> Date: Mon, 18 Oct 2021 20:12:49 +0000 (+0200) Subject: Move Introduction to new depository paradigm X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=a40f503fddc9f4b0b7619388e47a7f6d7eaaaff3;p=friendica.git Move Introduction to new depository paradigm --- diff --git a/doc/Developer-Domain-Driven-Design.md b/doc/Developer-Domain-Driven-Design.md index b8d886aa0d..1e77dd2f0b 100644 --- a/doc/Developer-Domain-Driven-Design.md +++ b/doc/Developer-Domain-Driven-Design.md @@ -36,17 +36,18 @@ doSomething($intros); ``` After: + ```php -function doSomething(\Friendica\Collection\Introductions $intros) +function doSomething(\Friendica\Contact\Introductions\Collection\Introductions $intros) { foreach ($intros as $intro) { - /** @var $intro \Friendica\Model\Introduction */ + /** @var $intro \Friendica\Contact\Introductions\Entity\Introduction */ $introId = $intro->id; } } -/** @var $intros \Friendica\Collection\Introductions */ -$intros = \Friendica\DI::intro()->select(['uid' => local_user()]); +/** @var $intros \Friendica\Contact\Introductions\Collection\Introductions */ +$intros = \Friendica\DI::intro()->selecForUser(local_user()); doSomething($intros); ``` diff --git a/src/Collection/Introductions.php b/src/Collection/Introductions.php deleted file mode 100644 index e95433193f..0000000000 --- a/src/Collection/Introductions.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php -/** - * @copyright Copyright (C) 2010-2021, the Friendica project - * - * @license GNU AGPL version 3 or any later version - * - * This program 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 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY 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 this program. If not, see <https://www.gnu.org/licenses/>. - * - */ - -namespace Friendica\Collection; - -use Friendica\BaseCollection; - -class Introductions extends BaseCollection -{ - -} diff --git a/src/Contact/Introduction/Collection/Introductions.php b/src/Contact/Introduction/Collection/Introductions.php new file mode 100644 index 0000000000..4df89cee43 --- /dev/null +++ b/src/Contact/Introduction/Collection/Introductions.php @@ -0,0 +1,9 @@ +<?php + +namespace Friendica\Contact\Introduction\Collection; + +use Friendica\BaseCollection; + +class Introductions extends BaseCollection +{ +} diff --git a/src/Contact/Introduction/Depository/Introduction.php b/src/Contact/Introduction/Depository/Introduction.php new file mode 100644 index 0000000000..f697c99009 --- /dev/null +++ b/src/Contact/Introduction/Depository/Introduction.php @@ -0,0 +1,168 @@ +<?php +/** + * @copyright Copyright (C) 2010-2021, the Friendica project + * + * @license GNU AGPL version 3 or any later version + * + * This program 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 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY 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 this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +namespace Friendica\Contact\Introduction\Depository; + +use Friendica\BaseDepository; +use Friendica\Contact\Introduction\Exception\IntroductionNotFoundException; +use Friendica\Contact\Introduction\Exception\IntroductionPersistenceException; +use Friendica\Contact\Introduction\Collection; +use Friendica\Contact\Introduction\Entity; +use Friendica\Contact\Introduction\Factory; +use Friendica\Database\Database; +use Friendica\Network\HTTPException\NotFoundException; +use Friendica\Util\DateTimeFormat; +use Psr\Log\LoggerInterface; + +class Introduction extends BaseDepository +{ + /** @var Factory\Introduction */ + protected $factory; + + protected static $table_name = 'intro'; + + public function __construct(Database $database, LoggerInterface $logger, Factory\Introduction $factory) + { + parent::__construct($database, $logger, $factory); + } + + /** + * @param array $condition + * @param array $params + * + * @return Entity\Introduction + * + * @throws NotFoundException the underlying exception if there's no Introduction with the given conditions + */ + private function selectOne(array $condition, array $params = []): Entity\Introduction + { + return parent::_selectOne($condition, $params); + } + + /** + * Converts a given Introduction into a DB compatible row array + * + * @param Entity\Introduction $introduction + * + * @return array + */ + protected function convertToTableRow(Entity\Introduction $introduction): array + { + return [ + 'uid' => $introduction->uid, + 'fid' => $introduction->fid, + 'contact-id' => $introduction->cid, + 'suggest-cid' => $introduction->sid, + 'knowyou' => $introduction->knowyou ? 1 : 0, + 'duplex' => $introduction->duplex ? 1 : 0, + 'note' => $introduction->note, + 'hash' => $introduction->hash, + 'blocked' => $introduction->blocked ? 1 : 0, + 'ignore' => $introduction->ignore ? 1 : 0 + ]; + } + + /** + * @param int $id + * @param int $uid + * + * @return Entity\Introduction + * + * @throws IntroductionNotFoundException in case there is no Introduction with this id + */ + public function selectOneById(int $id, int $uid): Entity\Introduction + { + try { + return $this->selectOne(['id' => $id, 'uid' => $uid]); + } catch (NotFoundException $exception) { + throw new IntroductionNotFoundException(sprintf('There is no Introduction with the ID %d for the user %d', $id, $uid), $exception); + } + } + + /** + * Selects introductions for a given user + * + * @param int $uid + * @param int|null $min_id + * @param int|null $max_id + * @param int $limit + * + * @return Collection\Introductions + */ + public function selectForUser(int $uid, int $min_id = null, int $max_id = null, int $limit = self::LIMIT): Collection\Introductions + { + try { + $BaseCollection = parent::_selectByBoundaries( + ['`uid = ?` AND NOT `ignore`',$uid], + ['order' => ['id' => 'DESC']], + $min_id, $max_id, $limit); + } catch (\Exception $e) { + throw new IntroductionPersistenceException(sprintf('Cannot select Introductions for used %d', $uid), $e); + } + + return new Collection\Introductions($BaseCollection->getArrayCopy(), $BaseCollection->getTotalCount()); + } + + /** + * @param Entity\Introduction $introduction + * + * @return bool + * + * @throws IntroductionPersistenceException in case the underlying storage cannot delete the Introduction + */ + public function delete(Entity\Introduction $introduction): bool + { + if (!$introduction->id) { + return false; + } + + try { + return $this->db->delete(self::$table_name, ['id' => $introduction->id]); + } catch (\Exception $e) { + throw new IntroductionPersistenceException(sprintf('Cannot delete Introduction with id %d', $introduction->id), $e); + } + } + + /** + * @param Entity\Introduction $introduction + * + * @return Entity\Introduction + * + * @throws IntroductionPersistenceException In case the underlying storage cannot save the Introduction + */ + public function save(Entity\Introduction $introduction): Entity\Introduction + { + try { + $fields = $this->convertToTableRow($introduction); + $fields['datetime'] = DateTimeFormat::utcNow(); + + if ($introduction->id) { + $this->db->update(self::$table_name, $fields, ['id' => $introduction->id]); + return $this->factory->createFromTableRow($fields); + } else { + $this->db->insert(self::$table_name, $fields); + return $this->selectOneById($this->db->lastInsertId(), $introduction->uid); + } + } catch (\Exception $exception) { + throw new IntroductionPersistenceException(sprintf('Cannot insert/update the Introduction %d for user %d', $introduction->id, $introduction->uid), $exception); + } + } +} diff --git a/src/Contact/Introduction/Entity/Introduction.php b/src/Contact/Introduction/Entity/Introduction.php new file mode 100644 index 0000000000..b9842a8429 --- /dev/null +++ b/src/Contact/Introduction/Entity/Introduction.php @@ -0,0 +1,98 @@ +<?php +/** + * @copyright Copyright (C) 2010-2021, the Friendica project + * + * @license GNU AGPL version 3 or any later version + * + * This program 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 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY 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 this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +namespace Friendica\Contact\Introduction\Entity; + +use Friendica\BaseEntity; + +/** + * @property-read int $uid + * @property-read int $fid + * @property-read int $cid + * @property-read int $sid + * @property-read bool $knowyou + * @property-read bool $duplex + * @property-read string $note + * @property-read string $hash + * @property-read \DateTime $datetime + * @property-read bool $blocked + * @property-read bool $ignore + * @property-read int|null $id + */ +class Introduction extends BaseEntity +{ + /** @var int */ + protected $uid; + /** @var int */ + protected $fid; + /** @var int */ + protected $cid; + /** @var int */ + protected $sid; + /** @var bool */ + protected $knowyou; + /** @var bool */ + protected $duplex; + /** @var string */ + protected $note; + /** @var string */ + protected $hash; + /** @var \DateTime */ + protected $datetime; + /** @var bool */ + protected $blocked; + /** @var bool */ + protected $ignore; + /** @var int|null */ + protected $id; + + /** + * @param int $uid + * @param int $fid + * @param int $cid + * @param bool $knowyou + * @param bool $duplex + * @param string $note + * @param string $hash + * @param bool $blocked + * @param bool $ignore + * @param int|null $id + */ + public function __construct(int $uid, int $fid, int $cid, int $sid, bool $knowyou, bool $duplex, string $note, string $hash, \DateTime $datetime, bool $blocked, bool $ignore, ?int $id) + { + $this->uid = $uid; + $this->fid = $fid; + $this->cid = $cid; + $this->sid = $sid; + $this->knowyou = $knowyou; + $this->duplex = $duplex; + $this->note = $note; + $this->hash = $hash; + $this->blocked = $blocked; + $this->ignore = $ignore; + $this->id = $id; + } + + public function setIgnore() + { + $this->ignore = true; + } +} diff --git a/src/Contact/Introduction/Exception/IntroductionNotFoundException.php b/src/Contact/Introduction/Exception/IntroductionNotFoundException.php new file mode 100644 index 0000000000..f48c9ea22c --- /dev/null +++ b/src/Contact/Introduction/Exception/IntroductionNotFoundException.php @@ -0,0 +1,11 @@ +<?php + +namespace Friendica\Contact\Introduction\Exception; + +class IntroductionNotFoundException extends \OutOfBoundsException +{ + public function __construct($message = "", \Throwable $previous = null) + { + parent::__construct($message, 404, $previous); + } +} diff --git a/src/Contact/Introduction/Exception/IntroductionPersistenceException.php b/src/Contact/Introduction/Exception/IntroductionPersistenceException.php new file mode 100644 index 0000000000..99fb919e38 --- /dev/null +++ b/src/Contact/Introduction/Exception/IntroductionPersistenceException.php @@ -0,0 +1,11 @@ +<?php + +namespace Friendica\Contact\Introduction\Exception; + +class IntroductionPersistenceException extends \RuntimeException +{ + public function __construct($message = "", \Throwable $previous = null) + { + parent::__construct($message, 500, $previous); + } +} diff --git a/src/Contact/Introduction/Factory/Introduction.php b/src/Contact/Introduction/Factory/Introduction.php new file mode 100644 index 0000000000..5f9d83734f --- /dev/null +++ b/src/Contact/Introduction/Factory/Introduction.php @@ -0,0 +1,50 @@ +<?php +/** + * @copyright Copyright (C) 2010-2021, the Friendica project + * + * @license GNU AGPL version 3 or any later version + * + * This program 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 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY 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 this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +namespace Friendica\Contact\Introduction\Factory; + +use Friendica\BaseFactory; +use Friendica\Contact\Introduction\Entity; +use Friendica\Capabilities\ICanCreateFromTableRow; + +class Introduction extends BaseFactory implements ICanCreateFromTableRow +{ + /** + * @inheritDoc + */ + public function createFromTableRow(array $row): Entity\Introduction + { + return new Entity\Introduction( + $row['uid'], + $row['fid'], + $row['contact-id'], + $row['suggested-cid'], + !empty($row['knowyou']), + !empty($row['dupley']), + $row['note'], + $row['hash'], + new \DateTime($row['datetime'], new \DateTimeZone('UTC')), + !empty($row['blocked']), + !empty($row['ignore']), + $row['id'] ?? null + ); + } +} diff --git a/src/DI.php b/src/DI.php index 31542e3d52..c00fb82c1d 100644 --- a/src/DI.php +++ b/src/DI.php @@ -435,11 +435,11 @@ abstract class DI } /** - * @return Repository\Introduction + * @return Contact\Introduction\Depository\Introduction */ public static function intro() { - return self::$dice->create(Repository\Introduction::class); + return self::$dice->create(Contact\Introduction\Depository\Introduction::class); } public static function permissionSet(): Security\PermissionSet\Depository\PermissionSet diff --git a/src/Factory/Api/Mastodon/FollowRequest.php b/src/Factory/Api/Mastodon/FollowRequest.php index f2be0e589a..1d90c55f04 100644 --- a/src/Factory/Api/Mastodon/FollowRequest.php +++ b/src/Factory/Api/Mastodon/FollowRequest.php @@ -23,9 +23,9 @@ namespace Friendica\Factory\Api\Mastodon; use Friendica\App\BaseURL; use Friendica\BaseFactory; +use Friendica\Contact\Introduction\Entity\Introduction; use Friendica\Model\APContact; use Friendica\Model\Contact; -use Friendica\Model\Introduction; use Friendica\Network\HTTPException; use ImagickException; use Psr\Log\LoggerInterface; @@ -49,7 +49,7 @@ class FollowRequest extends BaseFactory */ public function createFromIntroduction(Introduction $introduction): \Friendica\Object\Api\Mastodon\FollowRequest { - $cdata = Contact::getPublicAndUserContactID($introduction->{'contact-id'}, $introduction->uid); + $cdata = Contact::getPublicAndUserContactID($introduction->cid, $introduction->uid); if (empty($cdata)) { $this->logger->warning('Wrong introduction data', ['Introduction' => $introduction]); diff --git a/src/Model/Contact/Introduction.php b/src/Model/Contact/Introduction.php new file mode 100644 index 0000000000..692ba7befe --- /dev/null +++ b/src/Model/Contact/Introduction.php @@ -0,0 +1,144 @@ +<?php +/** + * @copyright Copyright (C) 2010-2021, the Friendica project + * + * @license GNU AGPL version 3 or any later version + * + * This program 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 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY 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 this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +namespace Friendica\Model\Contact; + +use Friendica\Contact\Introduction\Entity; +use Friendica\Core\Protocol; +use Friendica\DI; +use Friendica\Network\HTTPException; +use Friendica\Model\Contact; +use Friendica\Model\User; +use Friendica\Protocol\ActivityPub; +use Friendica\Protocol\Diaspora; +use Friendica\Util\DateTimeFormat; + +class Introduction +{ + /** + * Confirms a follow request and sends a notice to the remote contact. + * + * @param Entity\Introduction $introduction + * + * @throws HTTPException\InternalServerErrorException + * @throws HTTPException\NotFoundException + * @throws \ImagickException + */ + public static function confirm(Entity\Introduction $introduction): void + { + DI::logger()->info('Confirming follower', ['cid' => $introduction->cid]); + + $contact = Contact::selectFirst([], ['id' => $introduction->cid, 'uid' => $introduction->uid]); + + if (!$contact) { + throw new HTTPException\NotFoundException('Contact record not found.'); + } + + $newRelation = $contact['rel']; + $writable = $contact['writable']; + + if (!empty($contact['protocol'])) { + $protocol = $contact['protocol']; + } else { + $protocol = $contact['network']; + } + + if ($protocol == Protocol::ACTIVITYPUB) { + ActivityPub\Transmitter::sendContactAccept($contact['url'], $contact['hub-verify'], $contact['uid']); + } + + if (in_array($protocol, [Protocol::DIASPORA, Protocol::ACTIVITYPUB])) { + if ($introduction->duplex) { + $newRelation = Contact::FRIEND; + } else { + $newRelation = Contact::FOLLOWER; + } + + if ($newRelation != Contact::FOLLOWER) { + $writable = 1; + } + } + + $fields = [ + 'name-date' => DateTimeFormat::utcNow(), + 'uri-date' => DateTimeFormat::utcNow(), + 'blocked' => false, + 'pending' => false, + 'protocol' => $protocol, + 'writable' => $writable, + 'hidden' => $hidden ?? $contact['hidden'], + 'rel' => $newRelation, + ]; + Contact::update($fields, ['id' => $contact['id']]); + + array_merge($contact, $fields); + + if ($newRelation == Contact::FRIEND) { + if ($protocol == Protocol::DIASPORA) { + $ret = Diaspora::sendShare(User::getById($contact['uid']), $contact); + DI::logger()->info('share returns', ['return' => $ret]); + } elseif ($protocol == Protocol::ACTIVITYPUB) { + ActivityPub\Transmitter::sendActivity('Follow', $contact['url'], $contact['uid']); + } + } + } + + /** + * Discards the introduction and sends a rejection message to AP contacts. + * + * @param Entity\Introduction $introduction + * + * @throws HTTPException\InternalServerErrorException + * @throws \ImagickException + */ + public static function discard(Entity\Introduction $introduction): void + { + // If it is a friend suggestion, the contact is not a new friend but an existing friend + // that should not be deleted. + if (!$introduction->fid) { + // When the contact entry had been created just for that intro, we want to get rid of it now + $condition = [ + 'id' => $introduction->cid, + 'uid' => $introduction->uid, + 'self' => false, + 'pending' => true, + 'rel' => [0, Contact::FOLLOWER]]; + if (DI::dba()->exists('contact', $condition)) { + Contact::remove($introduction->cid); + } else { + Contact::update(['pending' => false], ['id' => $introduction->cid]); + } + } + + $contact = Contact::selectFirst([], ['id' => $introduction->cid, 'uid' => $introduction->uid]); + if (!empty($contact)) { + if (!empty($contact['protocol'])) { + $protocol = $contact['protocol']; + } else { + $protocol = $contact['network']; + } + + if ($protocol == Protocol::ACTIVITYPUB) { + ActivityPub\Transmitter::sendContactReject($contact['url'], $contact['hub-verify'], $contact['uid']); + } + } + } +} diff --git a/src/Model/Introduction.php b/src/Model/Introduction.php deleted file mode 100644 index aa71891214..0000000000 --- a/src/Model/Introduction.php +++ /dev/null @@ -1,181 +0,0 @@ -<?php -/** - * @copyright Copyright (C) 2010-2021, the Friendica project - * - * @license GNU AGPL version 3 or any later version - * - * This program 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 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY 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 this program. If not, see <https://www.gnu.org/licenses/>. - * - */ - -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 - * @property int fid - * @property int contact-id - * @property bool knowyou - * @property bool duplex - * @property string note - * @property string hash - * @property string datetime - * @property bool blocked - * @property bool ignore - */ -class Introduction extends BaseModel -{ - /** @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 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 - * @return bool - * @throws HTTPException\InternalServerErrorException - * @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]); - - if (!$contact) { - throw new HTTPException\NotFoundException('Contact record not found.'); - } - - $newRelation = $contact['rel']; - $writable = $contact['writable']; - - if (!empty($contact['protocol'])) { - $protocol = $contact['protocol']; - } else { - $protocol = $contact['network']; - } - - if ($protocol == Protocol::ACTIVITYPUB) { - ActivityPub\Transmitter::sendContactAccept($contact['url'], $contact['hub-verify'], $contact['uid']); - } - - if (in_array($protocol, [Protocol::DIASPORA, Protocol::ACTIVITYPUB])) { - if ($duplex) { - $newRelation = Contact::FRIEND; - } else { - $newRelation = Contact::FOLLOWER; - } - - if ($newRelation != Contact::FOLLOWER) { - $writable = 1; - } - } - - $fields = [ - 'name-date' => DateTimeFormat::utcNow(), - 'uri-date' => DateTimeFormat::utcNow(), - 'blocked' => false, - 'pending' => false, - 'protocol' => $protocol, - 'writable' => $writable, - 'hidden' => $hidden ?? $contact['hidden'], - 'rel' => $newRelation, - ]; - Contact::update($fields, ['id' => $contact['id']]); - - array_merge($contact, $fields); - - if ($newRelation == Contact::FRIEND) { - if ($protocol == Protocol::DIASPORA) { - $ret = Diaspora::sendShare(User::getById($contact['uid']), $contact); - $this->logger->info('share returns', ['return' => $ret]); - } elseif ($protocol == Protocol::ACTIVITYPUB) { - ActivityPub\Transmitter::sendActivity('Follow', $contact['url'], $contact['uid']); - } - } - - return $this->intro->delete($this); - } - - /** - * Silently ignores the introduction, hides it from notifications and prevents the remote contact from submitting - * additional follow requests. - * - * @return bool - * @throws \Exception - */ - public function ignore() - { - $this->ignore = true; - - 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 - */ - public function discard() - { - // If it is a friend suggestion, the contact is not a new friend but an existing friend - // that should not be deleted. - 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]]; - if ($this->dba->exists('contact', $condition)) { - Contact::remove($this->{'contact-id'}); - } else { - Contact::update(['pending' => false], ['id' => $this->{'contact-id'}]); - } - } - - $contact = Contact::selectFirst([], ['id' => $this->{'contact-id'}, 'uid' => $this->uid]); - if (!empty($contact)) { - if (!empty($contact['protocol'])) { - $protocol = $contact['protocol']; - } else { - $protocol = $contact['network']; - } - - if ($protocol == Protocol::ACTIVITYPUB) { - ActivityPub\Transmitter::sendContactReject($contact['url'], $contact['hub-verify'], $contact['uid']); - } - } - - return $this->intro->delete($this); - } -} diff --git a/src/Module/Api/Mastodon/FollowRequests.php b/src/Module/Api/Mastodon/FollowRequests.php index cb7d5da220..dc6f336d6d 100644 --- a/src/Module/Api/Mastodon/FollowRequests.php +++ b/src/Module/Api/Mastodon/FollowRequests.php @@ -23,6 +23,7 @@ namespace Friendica\Module\Api\Mastodon; use Friendica\Core\System; use Friendica\DI; +use Friendica\Model\Contact; use Friendica\Module\BaseApi; use Friendica\Network\HTTPException; @@ -34,7 +35,6 @@ class FollowRequests extends BaseApi /** * @param array $parameters * @throws HTTPException\BadRequestException - * @throws HTTPException\ForbiddenException * @throws HTTPException\InternalServerErrorException * @throws HTTPException\NotFoundException * @throws HTTPException\UnauthorizedException @@ -48,25 +48,28 @@ class FollowRequests extends BaseApi self::checkAllowedScope(self::SCOPE_FOLLOW); $uid = self::getCurrentUserID(); - $introduction = DI::intro()->selectFirst(['id' => $parameters['id'], 'uid' => $uid]); + $introduction = DI::intro()->selectOneById($parameters['id'], $uid); - $contactId = $introduction->{'contact-id'}; + $contactId = $introduction->cid; switch ($parameters['action']) { case 'authorize': - $introduction->confirm(); - + Contact\Introduction::confirm($introduction); $relationship = DI::mstdnRelationship()->createFromContactId($contactId, $uid); + + DI::intro()->delete($introduction); break; case 'ignore': - $introduction->ignore(); - + $introduction->setIgnore(); $relationship = DI::mstdnRelationship()->createFromContactId($contactId, $uid); + + DI::intro()->save($introduction); break; case 'reject': - $introduction->discard(); - + Contact\Introduction::discard($introduction); $relationship = DI::mstdnRelationship()->createFromContactId($contactId, $uid); + + DI::intro()->delete($introduction); break; default: throw new HTTPException\BadRequestException('Unexpected action parameter, expecting "authorize", "ignore" or "reject"'); @@ -92,13 +95,7 @@ class FollowRequests extends BaseApi 'limit' => 40, // Maximum number of results to return. Defaults to 40. Paginate using the HTTP Link header. ]); - $introductions = DI::intro()->selectByBoundaries( - ['`uid` = ? AND NOT `ignore`', $uid], - ['order' => ['id' => 'DESC']], - $request['min_id'], - $request['max_id'], - $request['limit'] - ); + $introductions = DI::intro()->selectForUser($uid, $request['min_id'], $request['max_id'], $request['limit']); $return = []; diff --git a/src/Module/FollowConfirm.php b/src/Module/FollowConfirm.php index f4e4c5ebf9..f028a3d388 100644 --- a/src/Module/FollowConfirm.php +++ b/src/Module/FollowConfirm.php @@ -21,12 +21,10 @@ class FollowConfirm extends BaseModule $duplex = intval($_POST['duplex'] ?? 0); $hidden = intval($_POST['hidden'] ?? 0); - $intro = DI::intro()->selectFirst(['id' => $intro_id, 'uid' => local_user()]); - - $cid = $intro->{'contact-id'}; + $intro = DI::intro()->selectOneById($intro_id, local_user()); $intro->confirm($duplex, $hidden); - DI::baseUrl()->redirect('contact/' . intval($cid)); + DI::baseUrl()->redirect('contact/' . $intro->cid); } } diff --git a/src/Module/Notifications/Notification.php b/src/Module/Notifications/Notification.php index 19ee410d28..403b43781c 100644 --- a/src/Module/Notifications/Notification.php +++ b/src/Module/Notifications/Notification.php @@ -24,6 +24,7 @@ namespace Friendica\Module\Notifications; use Friendica\BaseModule; use Friendica\Core\System; use Friendica\DI; +use Friendica\Model\Contact; use Friendica\Module\Security\Login; use Friendica\Network\HTTPException; @@ -50,14 +51,16 @@ class Notification extends BaseModule $request_id = $parameters['id'] ?? false; if ($request_id) { - $intro = DI::intro()->selectFirst(['id' => $request_id, 'uid' => local_user()]); + $intro = DI::intro()->selectOneById($request_id, local_user()); switch ($_POST['submit']) { case DI::l10n()->t('Discard'): - $intro->discard(); + Contact\Introduction::discard($intro); + DI::intro()->delete($intro); break; case DI::l10n()->t('Ignore'): - $intro->ignore(); + $intro->setIgnore(); + DI::intro()->save($intro); break; } diff --git a/src/Repository/Introduction.php b/src/Repository/Introduction.php deleted file mode 100644 index de95229bd5..0000000000 --- a/src/Repository/Introduction.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php -/** - * @copyright Copyright (C) 2010-2021, the Friendica project - * - * @license GNU AGPL version 3 or any later version - * - * This program 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 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY 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 this program. If not, see <https://www.gnu.org/licenses/>. - * - */ - -namespace Friendica\Repository; - -use Friendica\BaseRepository; -use Friendica\Collection; -use Friendica\Model; - -class Introduction extends BaseRepository -{ - protected static $table_name = 'intro'; - - protected static $model_class = Model\Introduction::class; - - protected static $collection_class = Collection\Introductions::class; - - /** - * @param array $data - * @return Model\Introduction - */ - protected function create(array $data) - { - return new Model\Introduction($this->dba, $this->logger, $this, $data); - } - - /** - * @param array $condition - * @return Model\Introduction - * @throws \Friendica\Network\HTTPException\NotFoundException - */ - public function selectFirst(array $condition) - { - return parent::selectFirst($condition); - } - - /** - * @param array $condition - * @param array $params - * @return Collection\Introductions - * @throws \Exception - */ - public function select(array $condition = [], array $params = []) - { - return parent::select($condition, $params); - } - - /** - * @param array $condition - * @param array $params - * @param int|null $min_id - * @param int|null $max_id - * @param int $limit - * @return Collection\Introductions - * @throws \Exception - */ - public function selectByBoundaries(array $condition = [], array $params = [], int $min_id = null, int $max_id = null, int $limit = self::LIMIT) - { - return parent::selectByBoundaries($condition, $params, $min_id, $max_id, $limit); - } -}