From a40f503fddc9f4b0b7619388e47a7f6d7eaaaff3 Mon Sep 17 00:00:00 2001 From: Philipp Date: Mon, 18 Oct 2021 22:12:49 +0200 Subject: [PATCH 01/14] Move Introduction to new depository paradigm --- doc/Developer-Domain-Driven-Design.md | 9 +- .../Introduction/Collection/Introductions.php | 9 + .../Introduction/Depository/Introduction.php | 168 ++++++++++++++++++ .../Introduction/Entity/Introduction.php | 98 ++++++++++ .../IntroductionNotFoundException.php | 11 ++ .../IntroductionPersistenceException.php | 11 ++ .../Introduction/Factory/Introduction.php} | 29 ++- src/DI.php | 4 +- src/Factory/Api/Mastodon/FollowRequest.php | 4 +- src/Model/{ => Contact}/Introduction.php | 93 +++------- src/Module/Api/Mastodon/FollowRequests.php | 29 ++- src/Module/FollowConfirm.php | 6 +- src/Module/Notifications/Notification.php | 9 +- src/Repository/Introduction.php | 79 -------- 14 files changed, 380 insertions(+), 179 deletions(-) create mode 100644 src/Contact/Introduction/Collection/Introductions.php create mode 100644 src/Contact/Introduction/Depository/Introduction.php create mode 100644 src/Contact/Introduction/Entity/Introduction.php create mode 100644 src/Contact/Introduction/Exception/IntroductionNotFoundException.php create mode 100644 src/Contact/Introduction/Exception/IntroductionPersistenceException.php rename src/{Collection/Introductions.php => Contact/Introduction/Factory/Introduction.php} (53%) rename src/Model/{ => Contact}/Introduction.php (60%) delete mode 100644 src/Repository/Introduction.php 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/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 @@ +. + * + */ + +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 @@ +. + * + */ + +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 @@ +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/Introduction.php b/src/Model/Contact/Introduction.php similarity index 60% rename from src/Model/Introduction.php rename to src/Model/Contact/Introduction.php index aa71891214..692ba7befe 100644 --- a/src/Model/Introduction.php +++ b/src/Model/Contact/Introduction.php @@ -19,64 +19,41 @@ * */ -namespace Friendica\Model; +namespace Friendica\Model\Contact; -use Friendica\BaseModel; +use Friendica\Contact\Introduction\Entity; use Friendica\Core\Protocol; -use Friendica\Database\Database; +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\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 +class Introduction { - /** @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 + * @param Entity\Introduction $introduction + * * @throws HTTPException\InternalServerErrorException * @throws HTTPException\NotFoundException * @throws \ImagickException */ - public function confirm(bool $duplex = false, bool $hidden = null) + public static function confirm(Entity\Introduction $introduction): void { - $this->logger->info('Confirming follower', ['cid' => $this->{'contact-id'}]); + DI::logger()->info('Confirming follower', ['cid' => $introduction->cid]); - $contact = Contact::selectFirst([], ['id' => $this->{'contact-id'}, 'uid' => $this->uid]); + $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']; + $writable = $contact['writable']; if (!empty($contact['protocol'])) { $protocol = $contact['protocol']; @@ -89,7 +66,7 @@ class Introduction extends BaseModel } if (in_array($protocol, [Protocol::DIASPORA, Protocol::ACTIVITYPUB])) { - if ($duplex) { + if ($introduction->duplex) { $newRelation = Contact::FRIEND; } else { $newRelation = Contact::FOLLOWER; @@ -117,53 +94,41 @@ class Introduction extends BaseModel if ($newRelation == Contact::FRIEND) { if ($protocol == Protocol::DIASPORA) { $ret = Diaspora::sendShare(User::getById($contact['uid']), $contact); - $this->logger->info('share returns', ['return' => $ret]); + DI::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 + * @param Entity\Introduction $introduction + * * @throws HTTPException\InternalServerErrorException - * @throws HTTPException\NotFoundException * @throws \ImagickException */ - public function discard() + 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 (!$this->fid) { + if (!$introduction->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'}); + $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' => $this->{'contact-id'}]); + Contact::update(['pending' => false], ['id' => $introduction->cid]); } } - $contact = Contact::selectFirst([], ['id' => $this->{'contact-id'}, 'uid' => $this->uid]); + $contact = Contact::selectFirst([], ['id' => $introduction->cid, 'uid' => $introduction->uid]); if (!empty($contact)) { if (!empty($contact['protocol'])) { $protocol = $contact['protocol']; @@ -175,7 +140,5 @@ class Introduction extends BaseModel 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 @@ -. - * - */ - -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); - } -} From 7d7d310cc4f8661751fd2a62e33405c98f78aa62 Mon Sep 17 00:00:00 2001 From: Philipp Date: Mon, 18 Oct 2021 22:49:25 +0200 Subject: [PATCH 02/14] Replace almost every Introduction places --- .../Introduction/Depository/Introduction.php | 42 +++++++++++++++-- .../Introduction/Entity/Introduction.php | 38 ++++++++------- .../Introduction/Factory/Introduction.php | 47 +++++++++++++++---- src/DI.php | 8 ++++ src/Model/Contact.php | 18 ++++--- src/Module/Delegation.php | 2 +- src/Protocol/DFRN.php | 13 +++-- src/Worker/Contact/RemoveContent.php | 3 +- 8 files changed, 128 insertions(+), 43 deletions(-) diff --git a/src/Contact/Introduction/Depository/Introduction.php b/src/Contact/Introduction/Depository/Introduction.php index f697c99009..280ae26d6e 100644 --- a/src/Contact/Introduction/Depository/Introduction.php +++ b/src/Contact/Introduction/Depository/Introduction.php @@ -76,7 +76,8 @@ class Introduction extends BaseDepository 'note' => $introduction->note, 'hash' => $introduction->hash, 'blocked' => $introduction->blocked ? 1 : 0, - 'ignore' => $introduction->ignore ? 1 : 0 + 'ignore' => $introduction->ignore ? 1 : 0, + 'datetime' => $introduction->datetime->format(DateTimeFormat::MYSQL), ]; } @@ -121,6 +122,42 @@ class Introduction extends BaseDepository return new Collection\Introductions($BaseCollection->getArrayCopy(), $BaseCollection->getTotalCount()); } + /** + * Selects the introduction for a given contact + * + * @param int $cid + * + * @return Entity\Introduction + * + * @throws IntroductionNotFoundException in case there is not Introduction for this contact + */ + public function selectForContact(int $cid): Entity\Introduction + { + try { + return $this->selectOne(['contact-id' => $cid]); + } catch (NotFoundException $exception) { + throw new IntroductionNotFoundException(sprintf('There is no Introduction for the contact %d', $cid), $exception); + } + } + + public function countActiveForUser($uid, array $params = []): int + { + try { + return $this->count(['blocked' => false, 'ignore' => false, 'uid' => $uid], $params); + } catch (\Exception $e) { + throw new IntroductionPersistenceException(sprintf('Cannot count Introductions for used %d', $uid), $e); + } + } + + public function existsForContact(int $cid, int $uid): bool + { + try { + return $this->exists(['uid' => $uid, 'suggest-cid' => $cid]); + } catch (\Exception $e) { + throw new IntroductionPersistenceException(sprintf('Cannot check Introductions for contact %d and user %d', $cid, $uid), $e); + } + } + /** * @param Entity\Introduction $introduction * @@ -151,8 +188,7 @@ class Introduction extends BaseDepository public function save(Entity\Introduction $introduction): Entity\Introduction { try { - $fields = $this->convertToTableRow($introduction); - $fields['datetime'] = DateTimeFormat::utcNow(); + $fields = $this->convertToTableRow($introduction); if ($introduction->id) { $this->db->update(self::$table_name, $fields, ['id' => $introduction->id]); diff --git a/src/Contact/Introduction/Entity/Introduction.php b/src/Contact/Introduction/Entity/Introduction.php index b9842a8429..59db24ffcf 100644 --- a/src/Contact/Introduction/Entity/Introduction.php +++ b/src/Contact/Introduction/Entity/Introduction.php @@ -25,9 +25,9 @@ use Friendica\BaseEntity; /** * @property-read int $uid - * @property-read int $fid - * @property-read int $cid * @property-read int $sid + * @property-read int|null $fid + * @property-read int|null $cid * @property-read bool $knowyou * @property-read bool $duplex * @property-read string $note @@ -42,11 +42,11 @@ class Introduction extends BaseEntity /** @var int */ protected $uid; /** @var int */ - protected $fid; - /** @var int */ - protected $cid; - /** @var int */ protected $sid; + /** @var int|null */ + protected $fid; + /** @var int|null */ + protected $cid; /** @var bool */ protected $knowyou; /** @var bool */ @@ -65,23 +65,25 @@ class Introduction extends BaseEntity 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 + * @param int $uid + * @param int $sid + * @param int|null $fid + * @param int|null $cid + * @param bool $knowyou + * @param bool $duplex + * @param string $note + * @param string $hash + * @param \DateTime $datetime + * @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) + public function __construct(int $uid, int $sid, ?int $fid, ?int $cid, bool $knowyou, bool $duplex, string $note, string $hash, \DateTime $datetime, bool $blocked, bool $ignore, ?int $id) { $this->uid = $uid; + $this->sid = $sid; $this->fid = $fid; $this->cid = $cid; - $this->sid = $sid; $this->knowyou = $knowyou; $this->duplex = $duplex; $this->note = $note; diff --git a/src/Contact/Introduction/Factory/Introduction.php b/src/Contact/Introduction/Factory/Introduction.php index 5f9d83734f..8fec61bb9f 100644 --- a/src/Contact/Introduction/Factory/Introduction.php +++ b/src/Contact/Introduction/Factory/Introduction.php @@ -24,6 +24,8 @@ namespace Friendica\Contact\Introduction\Factory; use Friendica\BaseFactory; use Friendica\Contact\Introduction\Entity; use Friendica\Capabilities\ICanCreateFromTableRow; +use Friendica\Util\DateTimeFormat; +use Friendica\Util\Strings; class Introduction extends BaseFactory implements ICanCreateFromTableRow { @@ -33,18 +35,47 @@ class Introduction extends BaseFactory implements ICanCreateFromTableRow public function createFromTableRow(array $row): Entity\Introduction { return new Entity\Introduction( - $row['uid'], - $row['fid'], - $row['contact-id'], - $row['suggested-cid'], + $row['uid'] ?? 0, + $row['suggest-cid'] ?? 0, + $row['fid'] ?? null, + $row['contact-id'] ?? null, !empty($row['knowyou']), - !empty($row['dupley']), - $row['note'], - $row['hash'], - new \DateTime($row['datetime'], new \DateTimeZone('UTC')), + !empty($row['duplex']), + $row['note'] ?? '', + $row['hash'] ?? '', + new \DateTime($row['datetime'] ?? 'now', new \DateTimeZone('UTC')), !empty($row['blocked']), !empty($row['ignore']), $row['id'] ?? null ); } + + public function createNew( + int $uid, + int $cid, + string $note, + int $fid = null, + int $sid = null, + bool $knowyou = false, + bool $duplex = false + ): Entity\Introduction { + return $this->createFromTableRow([ + 'uid' => $uid, + 'fid' => $fid, + 'contact-id' => $cid, + 'suggest-cid' => $sid, + 'knowyou' => $knowyou, + 'duplex' => $duplex, + 'note' => $note, + 'hash' => Strings::getRandomHex(), + 'datetime' => DateTimeFormat::utcNow(), + 'blocked' => false, + 'ignore' => false, + ]); + } + + public function createDummy(int $id): Entity\Introduction + { + return $this->createFromTableRow(['id' => $id]); + } } diff --git a/src/DI.php b/src/DI.php index c00fb82c1d..28df28a325 100644 --- a/src/DI.php +++ b/src/DI.php @@ -442,6 +442,14 @@ abstract class DI return self::$dice->create(Contact\Introduction\Depository\Introduction::class); } + /** + * @return Contact\Introduction\Factory\Introduction + */ + public static function introFactory() + { + return self::$dice->create(Contact\Introduction\Factory\Introduction::class); + } + public static function permissionSet(): Security\PermissionSet\Depository\PermissionSet { return self::$dice->create(Security\PermissionSet\Depository\PermissionSet::class); diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 06e546d614..0acb6d4d72 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -22,6 +22,7 @@ namespace Friendica\Model; use Friendica\App\BaseURL; +use Friendica\Contact\Introduction\Exception\IntroductionNotFoundException; use Friendica\Content\Pager; use Friendica\Content\Text\HTML; use Friendica\Core\Hook; @@ -1085,9 +1086,11 @@ class Contact ]; if (!empty($contact['pending'])) { - $intro = DBA::selectFirst('intro', ['id'], ['contact-id' => $contact['id']]); - if (DBA::isResult($intro)) { + try { + $intro = DI::intro()->selectForContact($contact['id']); $menu['follow'] = [DI::l10n()->t('Approve'), 'notifications/intros/' . $intro['id'], true]; + } catch (IntroductionNotFoundException $exception) { + DI::logger()->error('Pending contact doesn\'t have an introduction.', ['exception' => $exception]); } } } @@ -2706,12 +2709,13 @@ class Contact $user = DBA::selectFirst('user', $fields, ['uid' => $importer['uid']]); if (DBA::isResult($user) && !in_array($user['page-flags'], [User::PAGE_FLAGS_SOAPBOX, User::PAGE_FLAGS_FREELOVE, User::PAGE_FLAGS_COMMUNITY])) { // create notification - $hash = Strings::getRandomHex(); - if (is_array($contact_record)) { - DBA::insert('intro', ['uid' => $importer['uid'], 'contact-id' => $contact_record['id'], - 'blocked' => false, 'knowyou' => false, 'note' => $note, - 'hash' => $hash, 'datetime' => DateTimeFormat::utcNow()]); + $intro = DI::introFactory()->createNew( + $importer['uid'], + $contact_record['id'], + $note + ); + DI::intro()->save($intro); } Group::addMember(User::getDefaultGroup($importer['uid'], $contact_record["network"]), $contact_record['id']); diff --git a/src/Module/Delegation.php b/src/Module/Delegation.php index affe5e7b8f..12f8c5074c 100644 --- a/src/Module/Delegation.php +++ b/src/Module/Delegation.php @@ -133,7 +133,7 @@ class Delegation extends BaseModule $params = ['distinct' => true, 'expression' => 'convid']; $notifications += DBA::count('mail', ['uid' => $identity['uid'], 'seen' => false], $params); - $notifications += DBA::count('intro', ['blocked' => false, 'ignore' => false, 'uid' => $identity['uid']]); + $notifications += DI::intro()->countActiveForUser($identity['uid']); $identities[$key]['notifications'] = $notifications; } diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 8c511c2cd5..9246d85833 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -1352,7 +1352,7 @@ class DFRN } // Quit if we already have an introduction for this person - if (DBA::exists('intro', ['uid' => $uid, 'suggest-cid' => $cid])) { + if (DI::intro()->existsForContact($cid, $uid)) { return false; } @@ -1366,10 +1366,13 @@ class DFRN $suggest['title'] = ''; $suggest['body'] = $note; - $hash = Strings::getRandomHex(); - $fields = ['uid' => $suggest['uid'], 'suggest-cid' => $cid, 'contact-id' => $suggest['cid'], - 'note' => $suggest['body'], 'hash' => $hash, 'datetime' => DateTimeFormat::utcNow(), 'blocked' => false]; - DBA::insert('intro', $fields); + DI::intro()->save(DI::introFactory()->createNew( + $suggest['uid'], + $suggest['cid'], + $suggest['body'], + null, + $cid + )); DI::notify()->createFromArray([ 'type' => Notification\Type::SUGGEST, diff --git a/src/Worker/Contact/RemoveContent.php b/src/Worker/Contact/RemoveContent.php index 567cab1a86..f0e6e631d7 100644 --- a/src/Worker/Contact/RemoveContent.php +++ b/src/Worker/Contact/RemoveContent.php @@ -24,6 +24,7 @@ namespace Friendica\Worker\Contact; use Friendica\Core\Logger; use Friendica\Database\DBA; use Friendica\Database\DBStructure; +use Friendica\DI; use Friendica\Model\Photo; use Friendica\Model\Post; @@ -84,7 +85,7 @@ class RemoveContent DBA::delete('user-contact', ['cid' => $id]); DBA::delete('group_member', ['contact-id' => $id]); - DBA::delete('intro', ['contact-id' => $id]); + DI::intro()->delete(DI::introFactory()->createDummy($id)); return $contact; } From d2c210753ab5db72293144490b57dc0997878621 Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 19 Oct 2021 21:00:18 +0200 Subject: [PATCH 03/14] Remove logging leftover for debugging --- src/Profile/ProfileField/Depository/ProfileField.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Profile/ProfileField/Depository/ProfileField.php b/src/Profile/ProfileField/Depository/ProfileField.php index b792edf8f7..a6e441f3b6 100644 --- a/src/Profile/ProfileField/Depository/ProfileField.php +++ b/src/Profile/ProfileField/Depository/ProfileField.php @@ -86,7 +86,6 @@ class ProfileField extends BaseDepository $Entities = new Collection\ProfileFields(); foreach ($rows as $fields) { - $this->logger->warning('row', ['row' => $fields]); $Entities[] = $this->factory->createFromTableRow($fields); } From bf0782dc6bc2f645e34e20e3cc63665dc51849a9 Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 19 Oct 2021 21:04:24 +0200 Subject: [PATCH 04/14] Rename setIgnore() to ignore() --- src/Contact/Introduction/Entity/Introduction.php | 5 ++++- src/Module/Api/Mastodon/FollowRequests.php | 2 +- src/Module/Notifications/Notification.php | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Contact/Introduction/Entity/Introduction.php b/src/Contact/Introduction/Entity/Introduction.php index 59db24ffcf..44eddc2149 100644 --- a/src/Contact/Introduction/Entity/Introduction.php +++ b/src/Contact/Introduction/Entity/Introduction.php @@ -93,7 +93,10 @@ class Introduction extends BaseEntity $this->id = $id; } - public function setIgnore() + /** + * Ignore the current Introduction + */ + public function ignore() { $this->ignore = true; } diff --git a/src/Module/Api/Mastodon/FollowRequests.php b/src/Module/Api/Mastodon/FollowRequests.php index dc6f336d6d..bc7cc31bbe 100644 --- a/src/Module/Api/Mastodon/FollowRequests.php +++ b/src/Module/Api/Mastodon/FollowRequests.php @@ -60,7 +60,7 @@ class FollowRequests extends BaseApi DI::intro()->delete($introduction); break; case 'ignore': - $introduction->setIgnore(); + $introduction->ignore(); $relationship = DI::mstdnRelationship()->createFromContactId($contactId, $uid); DI::intro()->save($introduction); diff --git a/src/Module/Notifications/Notification.php b/src/Module/Notifications/Notification.php index 403b43781c..64ab459f12 100644 --- a/src/Module/Notifications/Notification.php +++ b/src/Module/Notifications/Notification.php @@ -59,7 +59,7 @@ class Notification extends BaseModule DI::intro()->delete($intro); break; case DI::l10n()->t('Ignore'): - $intro->setIgnore(); + $intro->ignore(); DI::intro()->save($intro); break; } From ed184bd592a074090f3c9c5e441674f000fd983f Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 19 Oct 2021 21:30:09 +0200 Subject: [PATCH 05/14] Set intro.blocked to deprecated --- database.sql | 2 +- doc/database/db_intro.md | 2 +- src/Contact/Introduction/Depository/Introduction.php | 3 +-- src/Contact/Introduction/Entity/Introduction.php | 7 +------ src/Contact/Introduction/Factory/Introduction.php | 2 -- static/dbstructure.config.php | 2 +- update.php | 10 +++++++++- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/database.sql b/database.sql index 466a8d9b77..43986e850e 100644 --- a/database.sql +++ b/database.sql @@ -719,7 +719,7 @@ CREATE TABLE IF NOT EXISTS `intro` ( `note` text COMMENT '', `hash` varchar(255) NOT NULL DEFAULT '' COMMENT '', `datetime` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '', - `blocked` boolean NOT NULL DEFAULT '1' COMMENT '', + `blocked` boolean NOT NULL DEFAULT '0' COMMENT 'deprecated', `ignore` boolean NOT NULL DEFAULT '0' COMMENT '', PRIMARY KEY(`id`), INDEX `contact-id` (`contact-id`), diff --git a/doc/database/db_intro.md b/doc/database/db_intro.md index da0cbe26ab..0f2e36c705 100644 --- a/doc/database/db_intro.md +++ b/doc/database/db_intro.md @@ -18,7 +18,7 @@ Fields | note | | text | YES | | NULL | | | hash | | varchar(255) | NO | | | | | datetime | | datetime | NO | | 0001-01-01 00:00:00 | | -| blocked | | boolean | NO | | 1 | | +| blocked | deprecated | boolean | NO | | 0 | | | ignore | | boolean | NO | | 0 | | Indexes diff --git a/src/Contact/Introduction/Depository/Introduction.php b/src/Contact/Introduction/Depository/Introduction.php index 280ae26d6e..3a4498cf3a 100644 --- a/src/Contact/Introduction/Depository/Introduction.php +++ b/src/Contact/Introduction/Depository/Introduction.php @@ -75,7 +75,6 @@ class Introduction extends BaseDepository 'duplex' => $introduction->duplex ? 1 : 0, 'note' => $introduction->note, 'hash' => $introduction->hash, - 'blocked' => $introduction->blocked ? 1 : 0, 'ignore' => $introduction->ignore ? 1 : 0, 'datetime' => $introduction->datetime->format(DateTimeFormat::MYSQL), ]; @@ -143,7 +142,7 @@ class Introduction extends BaseDepository public function countActiveForUser($uid, array $params = []): int { try { - return $this->count(['blocked' => false, 'ignore' => false, 'uid' => $uid], $params); + return $this->count(['ignore' => false, 'uid' => $uid], $params); } catch (\Exception $e) { throw new IntroductionPersistenceException(sprintf('Cannot count Introductions for used %d', $uid), $e); } diff --git a/src/Contact/Introduction/Entity/Introduction.php b/src/Contact/Introduction/Entity/Introduction.php index 44eddc2149..119fd1e06c 100644 --- a/src/Contact/Introduction/Entity/Introduction.php +++ b/src/Contact/Introduction/Entity/Introduction.php @@ -33,7 +33,6 @@ use Friendica\BaseEntity; * @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 */ @@ -58,8 +57,6 @@ class Introduction extends BaseEntity /** @var \DateTime */ protected $datetime; /** @var bool */ - protected $blocked; - /** @var bool */ protected $ignore; /** @var int|null */ protected $id; @@ -74,11 +71,10 @@ class Introduction extends BaseEntity * @param string $note * @param string $hash * @param \DateTime $datetime - * @param bool $blocked * @param bool $ignore * @param int|null $id */ - public function __construct(int $uid, int $sid, ?int $fid, ?int $cid, bool $knowyou, bool $duplex, string $note, string $hash, \DateTime $datetime, bool $blocked, bool $ignore, ?int $id) + public function __construct(int $uid, int $sid, ?int $fid, ?int $cid, bool $knowyou, bool $duplex, string $note, string $hash, \DateTime $datetime, bool $ignore, ?int $id) { $this->uid = $uid; $this->sid = $sid; @@ -88,7 +84,6 @@ class Introduction extends BaseEntity $this->duplex = $duplex; $this->note = $note; $this->hash = $hash; - $this->blocked = $blocked; $this->ignore = $ignore; $this->id = $id; } diff --git a/src/Contact/Introduction/Factory/Introduction.php b/src/Contact/Introduction/Factory/Introduction.php index 8fec61bb9f..35275de7f1 100644 --- a/src/Contact/Introduction/Factory/Introduction.php +++ b/src/Contact/Introduction/Factory/Introduction.php @@ -44,7 +44,6 @@ class Introduction extends BaseFactory implements ICanCreateFromTableRow $row['note'] ?? '', $row['hash'] ?? '', new \DateTime($row['datetime'] ?? 'now', new \DateTimeZone('UTC')), - !empty($row['blocked']), !empty($row['ignore']), $row['id'] ?? null ); @@ -69,7 +68,6 @@ class Introduction extends BaseFactory implements ICanCreateFromTableRow 'note' => $note, 'hash' => Strings::getRandomHex(), 'datetime' => DateTimeFormat::utcNow(), - 'blocked' => false, 'ignore' => false, ]); } diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index 4ed1e04a9b..c00cb0defb 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -782,7 +782,7 @@ return [ "note" => ["type" => "text", "comment" => ""], "hash" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], "datetime" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], - "blocked" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => ""], + "blocked" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "deprecated"], "ignore" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], ], "indexes" => [ diff --git a/update.php b/update.php index 25e64d659a..85f407d36c 100644 --- a/update.php +++ b/update.php @@ -1039,7 +1039,7 @@ function update_1440() return Update::SUCCESS; } -function update__1441() +function update_1441() { $languages = DI::l10n()->getAvailableLanguages(); @@ -1053,3 +1053,11 @@ function update__1441() return Update::SUCCESS; } + +function update_1442() +{ + // transform blocked intros into ignored intros + DBA::update('intro', ['ignore' => 1, 'blocked' => 0], ['blocked' => 1]); + + return Update::SUCCESS; +} From 690369cc4ba53ccc43e7df7de6e0fbcd70909b36 Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 19 Oct 2021 22:03:24 +0200 Subject: [PATCH 06/14] Fixings & add tests --- .../Introduction/Depository/Introduction.php | 1 - .../Introduction/Entity/Introduction.php | 26 ++-- .../Introduction/Factory/Introduction.php | 11 +- .../Introduction/Factory/IntroductionTest.php | 117 ++++++++++++++++++ 4 files changed, 132 insertions(+), 23 deletions(-) create mode 100644 tests/src/Contact/Introduction/Factory/IntroductionTest.php diff --git a/src/Contact/Introduction/Depository/Introduction.php b/src/Contact/Introduction/Depository/Introduction.php index 3a4498cf3a..249252d44a 100644 --- a/src/Contact/Introduction/Depository/Introduction.php +++ b/src/Contact/Introduction/Depository/Introduction.php @@ -68,7 +68,6 @@ class Introduction extends BaseDepository { return [ 'uid' => $introduction->uid, - 'fid' => $introduction->fid, 'contact-id' => $introduction->cid, 'suggest-cid' => $introduction->sid, 'knowyou' => $introduction->knowyou ? 1 : 0, diff --git a/src/Contact/Introduction/Entity/Introduction.php b/src/Contact/Introduction/Entity/Introduction.php index 119fd1e06c..7485f8181b 100644 --- a/src/Contact/Introduction/Entity/Introduction.php +++ b/src/Contact/Introduction/Entity/Introduction.php @@ -26,7 +26,6 @@ use Friendica\BaseEntity; /** * @property-read int $uid * @property-read int $sid - * @property-read int|null $fid * @property-read int|null $cid * @property-read bool $knowyou * @property-read bool $duplex @@ -43,8 +42,6 @@ class Introduction extends BaseEntity /** @var int */ protected $sid; /** @var int|null */ - protected $fid; - /** @var int|null */ protected $cid; /** @var bool */ protected $knowyou; @@ -64,7 +61,6 @@ class Introduction extends BaseEntity /** * @param int $uid * @param int $sid - * @param int|null $fid * @param int|null $cid * @param bool $knowyou * @param bool $duplex @@ -74,18 +70,18 @@ class Introduction extends BaseEntity * @param bool $ignore * @param int|null $id */ - public function __construct(int $uid, int $sid, ?int $fid, ?int $cid, bool $knowyou, bool $duplex, string $note, string $hash, \DateTime $datetime, bool $ignore, ?int $id) + public function __construct(int $uid, int $sid, ?int $cid, bool $knowyou, bool $duplex, string $note, string $hash, \DateTime $datetime, bool $ignore, ?int $id) { - $this->uid = $uid; - $this->sid = $sid; - $this->fid = $fid; - $this->cid = $cid; - $this->knowyou = $knowyou; - $this->duplex = $duplex; - $this->note = $note; - $this->hash = $hash; - $this->ignore = $ignore; - $this->id = $id; + $this->uid = $uid; + $this->sid = $sid; + $this->cid = $cid; + $this->knowyou = $knowyou; + $this->duplex = $duplex; + $this->note = $note; + $this->hash = $hash; + $this->datetime = $datetime; + $this->ignore = $ignore; + $this->id = $id; } /** diff --git a/src/Contact/Introduction/Factory/Introduction.php b/src/Contact/Introduction/Factory/Introduction.php index 35275de7f1..8aa5b7591a 100644 --- a/src/Contact/Introduction/Factory/Introduction.php +++ b/src/Contact/Introduction/Factory/Introduction.php @@ -37,7 +37,6 @@ class Introduction extends BaseFactory implements ICanCreateFromTableRow return new Entity\Introduction( $row['uid'] ?? 0, $row['suggest-cid'] ?? 0, - $row['fid'] ?? null, $row['contact-id'] ?? null, !empty($row['knowyou']), !empty($row['duplex']), @@ -51,18 +50,16 @@ class Introduction extends BaseFactory implements ICanCreateFromTableRow public function createNew( int $uid, - int $cid, + int $sid, string $note, - int $fid = null, - int $sid = null, + int $cid = null, bool $knowyou = false, bool $duplex = false ): Entity\Introduction { return $this->createFromTableRow([ 'uid' => $uid, - 'fid' => $fid, - 'contact-id' => $cid, 'suggest-cid' => $sid, + 'contact-id' => $cid, 'knowyou' => $knowyou, 'duplex' => $duplex, 'note' => $note, @@ -72,7 +69,7 @@ class Introduction extends BaseFactory implements ICanCreateFromTableRow ]); } - public function createDummy(int $id): Entity\Introduction + public function createDummy(?int $id): Entity\Introduction { return $this->createFromTableRow(['id' => $id]); } diff --git a/tests/src/Contact/Introduction/Factory/IntroductionTest.php b/tests/src/Contact/Introduction/Factory/IntroductionTest.php new file mode 100644 index 0000000000..9f45c54b06 --- /dev/null +++ b/tests/src/Contact/Introduction/Factory/IntroductionTest.php @@ -0,0 +1,117 @@ + [ + 'input' => [ + 'uid' => 42, + 'suggest-cid' => 13, + 'contact-id' => 24, + 'knowyou' => 1, + 'duplex' => 1, + 'note' => 'a note', + 'hash' => '12345', + 'datetime' => '1970-01-01 00:00:00', + 'ignore' => 0, + 'id' => 56, + ], + 'assertion' => [ + 'uid' => 42, + 'suggest-cid' => 13, + 'contact-id' => 24, + 'knowyou' => true, + 'duplex' => true, + 'note' => 'a note', + 'hash' => '12345', + 'datetime' => new \DateTime('1970-01-01 00:00:00', new \DateTimeZone('UTC')), + 'ignore' => false, + 'id' => 56, + ] + ], + 'empty' => [ + 'input' => [ + ], + 'assertion' => [ + 'uid' => 0, + 'suggest-cid' => 0, + 'contact-id' => null, + 'knowyou' => false, + 'duplex' => false, + 'note' => '', + 'ignore' => false, + 'id' => null, + ] + ], + ]; + } + + public function assertIntro(\Friendica\Contact\Introduction\Entity\Introduction $intro, array $assertion) + { + self::assertEquals($intro->id, $assertion['id'] ?? null); + self::assertEquals($intro->uid, $assertion['uid'] ?? 0); + self::assertEquals($intro->sid, $assertion['suggest-cid'] ?? 0); + self::assertEquals($intro->cid, $assertion['contact-id'] ?? null); + self::assertEquals($intro->knowyou, $assertion['knowyou'] ?? false); + self::assertEquals($intro->duplex, $assertion['duplex'] ?? false); + self::assertEquals($intro->note, $assertion['note'] ?? ''); + if (isset($assertion['hash'])) { + self::assertEquals($intro->hash, $assertion['hash']); + } else { + self::assertIsString($intro->hash); + } + if (isset($assertion['datetime'])) { + self::assertEquals($intro->datetime, $assertion['datetime']); + } else { + self::assertInstanceOf(\DateTime::class, $intro->datetime); + } + self::assertEquals($intro->ignore, $assertion['ignore'] ?? false); + } + + /** + * @dataProvider dataRow + */ + public function testCreateFromTableRow(array $input, array $assertion) + { + $factory = new Introduction(new NullLogger()); + + $intro = $factory->createFromTableRow($input); + $this->assertIntro($intro, $assertion); + } + + /** + * @dataProvider dataRow + */ + public function testCreateNew(array $input, array $assertion) + { + $factory = new Introduction(new NullLogger()); + + $intro = $factory->createNew($input['uid'] ?? 0, $input['sid'] ?? 0, $input['note'] ?? ''); + + $this->assertIntro($intro, [ + 'uid' => $input['uid'] ?? 0, + 'sid' => $input['sid'] ?? 0, + 'note' => $input['note'] ?? '', + ]); + } + + /** + * @dataProvider dataRow + */ + public function testCreateDummy(array $input, array $assertion) + { + $factory = new Introduction(new NullLogger()); + + $intro = $factory->createDummy($input['id'] ?? null); + + $this->assertIntro($intro, ['id' => $input['id'] ?? null]); + } +} From b4572a529376bc9e2e1c5396a4061ac499d7d7e9 Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 19 Oct 2021 22:59:19 +0200 Subject: [PATCH 07/14] Update DB version --- database.sql | 2 +- static/dbstructure.config.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/database.sql b/database.sql index 43986e850e..178c3fed6f 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2021.12-dev (Siberian Iris) --- DB_UPDATE_VERSION 1441 +-- DB_UPDATE_VERSION 1442 -- ------------------------------------------ diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index c00cb0defb..4e478f0342 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -55,7 +55,7 @@ use Friendica\Database\DBA; if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1441); + define('DB_UPDATE_VERSION', 1442); } return [ From 44627a0b12e339901c9ca686e43df48c8db88b52 Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 19 Oct 2021 23:11:47 +0200 Subject: [PATCH 08/14] fix intro.cid and intro.suggest-id --- .../Introduction/Depository/Introduction.php | 14 +++++++++++--- src/Contact/Introduction/Entity/Introduction.php | 16 ++++++++-------- .../Introduction/Factory/Introduction.php | 8 ++++---- src/Protocol/DFRN.php | 2 +- .../Introduction/Factory/IntroductionTest.php | 16 ++++++++-------- 5 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/Contact/Introduction/Depository/Introduction.php b/src/Contact/Introduction/Depository/Introduction.php index 249252d44a..b9752d8112 100644 --- a/src/Contact/Introduction/Depository/Introduction.php +++ b/src/Contact/Introduction/Depository/Introduction.php @@ -147,12 +147,20 @@ class Introduction extends BaseDepository } } - public function existsForContact(int $cid, int $uid): bool + /** + * Checks, if the suggested contact already exists for the user + * + * @param int $sid + * @param int $uid + * + * @return bool + */ + public function suggestionExistsForUser(int $sid, int $uid): bool { try { - return $this->exists(['uid' => $uid, 'suggest-cid' => $cid]); + return $this->exists(['uid' => $uid, 'suggest-cid' => $sid]); } catch (\Exception $e) { - throw new IntroductionPersistenceException(sprintf('Cannot check Introductions for contact %d and user %d', $cid, $uid), $e); + throw new IntroductionPersistenceException(sprintf('Cannot check suggested Introduction for contact %d and user %d', $sid, $uid), $e); } } diff --git a/src/Contact/Introduction/Entity/Introduction.php b/src/Contact/Introduction/Entity/Introduction.php index 7485f8181b..af9db729aa 100644 --- a/src/Contact/Introduction/Entity/Introduction.php +++ b/src/Contact/Introduction/Entity/Introduction.php @@ -25,8 +25,8 @@ use Friendica\BaseEntity; /** * @property-read int $uid - * @property-read int $sid - * @property-read int|null $cid + * @property-read int $cid + * @property-read int|null $sid * @property-read bool $knowyou * @property-read bool $duplex * @property-read string $note @@ -40,9 +40,9 @@ class Introduction extends BaseEntity /** @var int */ protected $uid; /** @var int */ - protected $sid; - /** @var int|null */ protected $cid; + /** @var int|null */ + protected $sid; /** @var bool */ protected $knowyou; /** @var bool */ @@ -60,8 +60,8 @@ class Introduction extends BaseEntity /** * @param int $uid - * @param int $sid - * @param int|null $cid + * @param int $cid + * @param int|null $sid * @param bool $knowyou * @param bool $duplex * @param string $note @@ -70,11 +70,11 @@ class Introduction extends BaseEntity * @param bool $ignore * @param int|null $id */ - public function __construct(int $uid, int $sid, ?int $cid, bool $knowyou, bool $duplex, string $note, string $hash, \DateTime $datetime, bool $ignore, ?int $id) + public function __construct(int $uid, int $cid, ?int $sid, bool $knowyou, bool $duplex, string $note, string $hash, \DateTime $datetime, bool $ignore, ?int $id) { $this->uid = $uid; - $this->sid = $sid; $this->cid = $cid; + $this->sid = $sid; $this->knowyou = $knowyou; $this->duplex = $duplex; $this->note = $note; diff --git a/src/Contact/Introduction/Factory/Introduction.php b/src/Contact/Introduction/Factory/Introduction.php index 8aa5b7591a..57598f5e80 100644 --- a/src/Contact/Introduction/Factory/Introduction.php +++ b/src/Contact/Introduction/Factory/Introduction.php @@ -36,8 +36,8 @@ class Introduction extends BaseFactory implements ICanCreateFromTableRow { return new Entity\Introduction( $row['uid'] ?? 0, - $row['suggest-cid'] ?? 0, - $row['contact-id'] ?? null, + $row['contact-id'] ?? 0, + $row['suggest-cid'] ?? null, !empty($row['knowyou']), !empty($row['duplex']), $row['note'] ?? '', @@ -50,9 +50,9 @@ class Introduction extends BaseFactory implements ICanCreateFromTableRow public function createNew( int $uid, - int $sid, + int $cid, string $note, - int $cid = null, + int $sid = null, bool $knowyou = false, bool $duplex = false ): Entity\Introduction { diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 9246d85833..a9918bbd02 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -1352,7 +1352,7 @@ class DFRN } // Quit if we already have an introduction for this person - if (DI::intro()->existsForContact($cid, $uid)) { + if (DI::intro()->suggestionExistsForUser($cid, $uid)) { return false; } diff --git a/tests/src/Contact/Introduction/Factory/IntroductionTest.php b/tests/src/Contact/Introduction/Factory/IntroductionTest.php index 9f45c54b06..529d2720ef 100644 --- a/tests/src/Contact/Introduction/Factory/IntroductionTest.php +++ b/tests/src/Contact/Introduction/Factory/IntroductionTest.php @@ -42,8 +42,8 @@ class IntroductionTest extends TestCase ], 'assertion' => [ 'uid' => 0, - 'suggest-cid' => 0, - 'contact-id' => null, + 'contact-id' => 0, + 'suggest-cid' => null, 'knowyou' => false, 'duplex' => false, 'note' => '', @@ -58,8 +58,8 @@ class IntroductionTest extends TestCase { self::assertEquals($intro->id, $assertion['id'] ?? null); self::assertEquals($intro->uid, $assertion['uid'] ?? 0); - self::assertEquals($intro->sid, $assertion['suggest-cid'] ?? 0); - self::assertEquals($intro->cid, $assertion['contact-id'] ?? null); + self::assertEquals($intro->cid, $assertion['contact-id'] ?? 0); + self::assertEquals($intro->sid, $assertion['suggest-cid'] ?? null); self::assertEquals($intro->knowyou, $assertion['knowyou'] ?? false); self::assertEquals($intro->duplex, $assertion['duplex'] ?? false); self::assertEquals($intro->note, $assertion['note'] ?? ''); @@ -94,12 +94,12 @@ class IntroductionTest extends TestCase { $factory = new Introduction(new NullLogger()); - $intro = $factory->createNew($input['uid'] ?? 0, $input['sid'] ?? 0, $input['note'] ?? ''); + $intro = $factory->createNew($input['uid'] ?? 0, $input['cid'] ?? 0, $input['note'] ?? ''); $this->assertIntro($intro, [ - 'uid' => $input['uid'] ?? 0, - 'sid' => $input['sid'] ?? 0, - 'note' => $input['note'] ?? '', + 'uid' => $input['uid'] ?? 0, + 'contact-id' => $input['cid'] ?? 0, + 'note' => $input['note'] ?? '', ]); } From 3153e098b0e83910a550773f5661d4e8541b14b7 Mon Sep 17 00:00:00 2001 From: Philipp Date: Thu, 21 Oct 2021 21:34:49 +0200 Subject: [PATCH 09/14] Remove deprecated, impossible code for discarding with FID --- src/Model/Contact/Introduction.php | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/Model/Contact/Introduction.php b/src/Model/Contact/Introduction.php index 692ba7befe..7524711371 100644 --- a/src/Model/Contact/Introduction.php +++ b/src/Model/Contact/Introduction.php @@ -111,23 +111,6 @@ class Introduction */ 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'])) { From d67b676ce54ad855b6734820456b6b63c2cf94e3 Mon Sep 17 00:00:00 2001 From: Philipp Date: Thu, 21 Oct 2021 21:41:26 +0200 Subject: [PATCH 10/14] Fix confirm parameter --- src/Model/Contact/Introduction.php | 6 ++++-- src/Module/FollowConfirm.php | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Model/Contact/Introduction.php b/src/Model/Contact/Introduction.php index 7524711371..f27a4a6ba8 100644 --- a/src/Model/Contact/Introduction.php +++ b/src/Model/Contact/Introduction.php @@ -37,12 +37,14 @@ class Introduction * Confirms a follow request and sends a notice to the remote contact. * * @param Entity\Introduction $introduction + * @param bool $duplex + * @param bool $hidden * * @throws HTTPException\InternalServerErrorException * @throws HTTPException\NotFoundException * @throws \ImagickException */ - public static function confirm(Entity\Introduction $introduction): void + public static function confirm(Entity\Introduction $introduction, bool $duplex = false, bool $hidden = false): void { DI::logger()->info('Confirming follower', ['cid' => $introduction->cid]); @@ -66,7 +68,7 @@ class Introduction } if (in_array($protocol, [Protocol::DIASPORA, Protocol::ACTIVITYPUB])) { - if ($introduction->duplex) { + if ($duplex) { $newRelation = Contact::FRIEND; } else { $newRelation = Contact::FOLLOWER; diff --git a/src/Module/FollowConfirm.php b/src/Module/FollowConfirm.php index f028a3d388..3015c3b649 100644 --- a/src/Module/FollowConfirm.php +++ b/src/Module/FollowConfirm.php @@ -3,6 +3,7 @@ namespace Friendica\Module; use Friendica\BaseModule; use Friendica\DI; +use Friendica\Model\Contact; /** * Process follow request confirmations @@ -23,7 +24,7 @@ class FollowConfirm extends BaseModule $intro = DI::intro()->selectOneById($intro_id, local_user()); - $intro->confirm($duplex, $hidden); + Contact\Introduction::confirm($intro, $duplex, $hidden); DI::baseUrl()->redirect('contact/' . $intro->cid); } From f5786a8f4f55f0a70b84b38c73163ce8232894f5 Mon Sep 17 00:00:00 2001 From: Philipp Date: Thu, 21 Oct 2021 21:48:23 +0200 Subject: [PATCH 11/14] set intro::duplex deprecated because of no usage --- database.sql | 2 +- doc/database/db_intro.md | 2 +- src/Contact/Introduction/Depository/Introduction.php | 1 - src/Contact/Introduction/Entity/Introduction.php | 7 +------ src/Contact/Introduction/Factory/Introduction.php | 5 +---- static/dbstructure.config.php | 2 +- .../src/Contact/Introduction/Factory/IntroductionTest.php | 4 ---- 7 files changed, 5 insertions(+), 18 deletions(-) diff --git a/database.sql b/database.sql index 178c3fed6f..fcbcbb3941 100644 --- a/database.sql +++ b/database.sql @@ -715,7 +715,7 @@ CREATE TABLE IF NOT EXISTS `intro` ( `contact-id` int unsigned NOT NULL DEFAULT 0 COMMENT '', `suggest-cid` int unsigned COMMENT 'Suggested contact', `knowyou` boolean NOT NULL DEFAULT '0' COMMENT '', - `duplex` boolean NOT NULL DEFAULT '0' COMMENT '', + `duplex` boolean NOT NULL DEFAULT '0' COMMENT 'deprecated', `note` text COMMENT '', `hash` varchar(255) NOT NULL DEFAULT '' COMMENT '', `datetime` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '', diff --git a/doc/database/db_intro.md b/doc/database/db_intro.md index 0f2e36c705..3db6240d03 100644 --- a/doc/database/db_intro.md +++ b/doc/database/db_intro.md @@ -14,7 +14,7 @@ Fields | contact-id | | int unsigned | NO | | 0 | | | suggest-cid | Suggested contact | int unsigned | YES | | NULL | | | knowyou | | boolean | NO | | 0 | | -| duplex | | boolean | NO | | 0 | | +| duplex | deprecated | boolean | NO | | 0 | | | note | | text | YES | | NULL | | | hash | | varchar(255) | NO | | | | | datetime | | datetime | NO | | 0001-01-01 00:00:00 | | diff --git a/src/Contact/Introduction/Depository/Introduction.php b/src/Contact/Introduction/Depository/Introduction.php index b9752d8112..792673f23b 100644 --- a/src/Contact/Introduction/Depository/Introduction.php +++ b/src/Contact/Introduction/Depository/Introduction.php @@ -71,7 +71,6 @@ class Introduction extends BaseDepository 'contact-id' => $introduction->cid, 'suggest-cid' => $introduction->sid, 'knowyou' => $introduction->knowyou ? 1 : 0, - 'duplex' => $introduction->duplex ? 1 : 0, 'note' => $introduction->note, 'hash' => $introduction->hash, 'ignore' => $introduction->ignore ? 1 : 0, diff --git a/src/Contact/Introduction/Entity/Introduction.php b/src/Contact/Introduction/Entity/Introduction.php index af9db729aa..9c5fb060ec 100644 --- a/src/Contact/Introduction/Entity/Introduction.php +++ b/src/Contact/Introduction/Entity/Introduction.php @@ -28,7 +28,6 @@ use Friendica\BaseEntity; * @property-read int $cid * @property-read int|null $sid * @property-read bool $knowyou - * @property-read bool $duplex * @property-read string $note * @property-read string $hash * @property-read \DateTime $datetime @@ -45,8 +44,6 @@ class Introduction extends BaseEntity protected $sid; /** @var bool */ protected $knowyou; - /** @var bool */ - protected $duplex; /** @var string */ protected $note; /** @var string */ @@ -63,20 +60,18 @@ class Introduction extends BaseEntity * @param int $cid * @param int|null $sid * @param bool $knowyou - * @param bool $duplex * @param string $note * @param string $hash * @param \DateTime $datetime * @param bool $ignore * @param int|null $id */ - public function __construct(int $uid, int $cid, ?int $sid, bool $knowyou, bool $duplex, string $note, string $hash, \DateTime $datetime, bool $ignore, ?int $id) + public function __construct(int $uid, int $cid, ?int $sid, bool $knowyou, string $note, string $hash, \DateTime $datetime, bool $ignore, ?int $id) { $this->uid = $uid; $this->cid = $cid; $this->sid = $sid; $this->knowyou = $knowyou; - $this->duplex = $duplex; $this->note = $note; $this->hash = $hash; $this->datetime = $datetime; diff --git a/src/Contact/Introduction/Factory/Introduction.php b/src/Contact/Introduction/Factory/Introduction.php index 57598f5e80..3bfa166b29 100644 --- a/src/Contact/Introduction/Factory/Introduction.php +++ b/src/Contact/Introduction/Factory/Introduction.php @@ -39,7 +39,6 @@ class Introduction extends BaseFactory implements ICanCreateFromTableRow $row['contact-id'] ?? 0, $row['suggest-cid'] ?? null, !empty($row['knowyou']), - !empty($row['duplex']), $row['note'] ?? '', $row['hash'] ?? '', new \DateTime($row['datetime'] ?? 'now', new \DateTimeZone('UTC')), @@ -53,15 +52,13 @@ class Introduction extends BaseFactory implements ICanCreateFromTableRow int $cid, string $note, int $sid = null, - bool $knowyou = false, - bool $duplex = false + bool $knowyou = false ): Entity\Introduction { return $this->createFromTableRow([ 'uid' => $uid, 'suggest-cid' => $sid, 'contact-id' => $cid, 'knowyou' => $knowyou, - 'duplex' => $duplex, 'note' => $note, 'hash' => Strings::getRandomHex(), 'datetime' => DateTimeFormat::utcNow(), diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index 4e478f0342..0019fdf7bf 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -778,7 +778,7 @@ return [ "contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id"], "comment" => ""], "suggest-cid" => ["type" => "int unsigned", "foreign" => ["contact" => "id"], "comment" => "Suggested contact"], "knowyou" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], - "duplex" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""], + "duplex" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "deprecated"], "note" => ["type" => "text", "comment" => ""], "hash" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""], "datetime" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""], diff --git a/tests/src/Contact/Introduction/Factory/IntroductionTest.php b/tests/src/Contact/Introduction/Factory/IntroductionTest.php index 529d2720ef..e5efd03ddc 100644 --- a/tests/src/Contact/Introduction/Factory/IntroductionTest.php +++ b/tests/src/Contact/Introduction/Factory/IntroductionTest.php @@ -17,7 +17,6 @@ class IntroductionTest extends TestCase 'suggest-cid' => 13, 'contact-id' => 24, 'knowyou' => 1, - 'duplex' => 1, 'note' => 'a note', 'hash' => '12345', 'datetime' => '1970-01-01 00:00:00', @@ -29,7 +28,6 @@ class IntroductionTest extends TestCase 'suggest-cid' => 13, 'contact-id' => 24, 'knowyou' => true, - 'duplex' => true, 'note' => 'a note', 'hash' => '12345', 'datetime' => new \DateTime('1970-01-01 00:00:00', new \DateTimeZone('UTC')), @@ -45,7 +43,6 @@ class IntroductionTest extends TestCase 'contact-id' => 0, 'suggest-cid' => null, 'knowyou' => false, - 'duplex' => false, 'note' => '', 'ignore' => false, 'id' => null, @@ -61,7 +58,6 @@ class IntroductionTest extends TestCase self::assertEquals($intro->cid, $assertion['contact-id'] ?? 0); self::assertEquals($intro->sid, $assertion['suggest-cid'] ?? null); self::assertEquals($intro->knowyou, $assertion['knowyou'] ?? false); - self::assertEquals($intro->duplex, $assertion['duplex'] ?? false); self::assertEquals($intro->note, $assertion['note'] ?? ''); if (isset($assertion['hash'])) { self::assertEquals($intro->hash, $assertion['hash']); From bf7c66b2c794c1de45efe81fbe59e830afcfa5eb Mon Sep 17 00:00:00 2001 From: Philipp Date: Thu, 21 Oct 2021 21:53:58 +0200 Subject: [PATCH 12/14] Fix Model\Contact\Introduction::confirm() --- src/Model/Contact/Introduction.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Model/Contact/Introduction.php b/src/Model/Contact/Introduction.php index f27a4a6ba8..b85e90eaed 100644 --- a/src/Model/Contact/Introduction.php +++ b/src/Model/Contact/Introduction.php @@ -37,14 +37,14 @@ class Introduction * Confirms a follow request and sends a notice to the remote contact. * * @param Entity\Introduction $introduction - * @param bool $duplex - * @param bool $hidden + * @param bool $duplex Is it a follow back? + * @param bool|null $hidden Should this contact be hidden? null = no change * * @throws HTTPException\InternalServerErrorException * @throws HTTPException\NotFoundException * @throws \ImagickException */ - public static function confirm(Entity\Introduction $introduction, bool $duplex = false, bool $hidden = false): void + public static function confirm(Entity\Introduction $introduction, bool $duplex = false, ?bool $hidden = null): void { DI::logger()->info('Confirming follower', ['cid' => $introduction->cid]); From e1574dc2e76e89fa2d04f54ffc4c511ddb1eec80 Mon Sep 17 00:00:00 2001 From: Philipp Date: Thu, 21 Oct 2021 22:11:15 +0200 Subject: [PATCH 13/14] Fix foreign key violation for Notify insert with uri_id/parent_uri_id 0 instead NULL --- src/Navigation/Notifications/Depository/Notify.php | 4 ++-- src/Navigation/Notifications/Entity/Notify.php | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Navigation/Notifications/Depository/Notify.php b/src/Navigation/Notifications/Depository/Notify.php index 06de36c638..a380166c61 100644 --- a/src/Navigation/Notifications/Depository/Notify.php +++ b/src/Navigation/Notifications/Depository/Notify.php @@ -485,9 +485,9 @@ class Notify extends BaseDepository private function storeAndSend($params, $sitelink, $tsitelink, $hsitelink, $title, $subject, $preamble, $epreamble, $body, $itemlink, $show_in_notification_page) { $item_id = $params['item']['id'] ?? 0; - $uri_id = $params['item']['uri-id'] ?? 0; + $uri_id = $params['item']['uri-id'] ?? null; $parent_id = $params['item']['parent'] ?? 0; - $parent_uri_id = $params['item']['parent-uri-id'] ?? 0; + $parent_uri_id = $params['item']['parent-uri-id'] ?? null; // Ensure that the important fields are set at any time $fields = ['nickname']; diff --git a/src/Navigation/Notifications/Entity/Notify.php b/src/Navigation/Notifications/Entity/Notify.php index 88cd8ab36e..1a97835b6e 100644 --- a/src/Navigation/Notifications/Entity/Notify.php +++ b/src/Navigation/Notifications/Entity/Notify.php @@ -60,14 +60,14 @@ class Notify extends BaseEntity protected $name_cache; /** @var string */ protected $msg_cache; - /** @var int */ + /** @var int|null */ protected $uriId; - /** @var int */ + /** @var int|null */ protected $parentUriId; /** @var int */ protected $id; - public function __construct(int $type, string $name, UriInterface $url, UriInterface $photo, DateTime $date, int $uid, UriInterface $link, bool $seen, string $verb, string $otype, string $name_cache, string $msg = null, string $msg_cache = null, int $itemId = null, int $uriId = null, int $parent = null, int $parentUriId = null, int $id = null) + public function __construct(int $type, string $name, UriInterface $url, UriInterface $photo, DateTime $date, int $uid, UriInterface $link, bool $seen, string $verb, string $otype, string $name_cache, string $msg = null, string $msg_cache = null, int $itemId = null, int $uriId = null, int $parent = null, ?int $parentUriId = null, ?int $id = null) { $this->type = $type; $this->name = $name; From 1cb76d23ffc16188b79d31ac0dd2077961855b77 Mon Sep 17 00:00:00 2001 From: Philipp Date: Thu, 21 Oct 2021 22:18:32 +0200 Subject: [PATCH 14/14] Delete the intro after confirming it ;-) --- src/Module/FollowConfirm.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Module/FollowConfirm.php b/src/Module/FollowConfirm.php index 3015c3b649..75153512b6 100644 --- a/src/Module/FollowConfirm.php +++ b/src/Module/FollowConfirm.php @@ -25,6 +25,7 @@ class FollowConfirm extends BaseModule $intro = DI::intro()->selectOneById($intro_id, local_user()); Contact\Introduction::confirm($intro, $duplex, $hidden); + DI::intro()->delete($intro); DI::baseUrl()->redirect('contact/' . $intro->cid); }