diff --git a/src/Contact/LocalRelationship/Entity/LocalRelationship.php b/src/Contact/LocalRelationship/Entity/LocalRelationship.php new file mode 100644 index 0000000000..e5e85c60de --- /dev/null +++ b/src/Contact/LocalRelationship/Entity/LocalRelationship.php @@ -0,0 +1,128 @@ +. + * + */ + +namespace Friendica\Contact\LocalRelationship\Entity; + +use Friendica\Core\Protocol; +use Friendica\Model\Contact; + +/** + * @property-read int $userId + * @property-read int $contactId + * @property-read int $uriId + * @property-read bool $blocked + * @property-read bool $ignored + * @property-read bool $collapsed + * @property-read bool $hidden + * @property-read bool $pending + * @property-read int $rel + * @property-read string $info + * @property-read bool $notifyNewPosts + * @property-read bool $isRemoteSelf + * @property-read int $fetchFurtherInformation + * @property-read string $ffiKeywordDenylist + * @property-read bool $subhub + * @property-read string $hubVerify + * @property-read string $protocol + * @property-read int $rating + * @property-read int $priority + */ +class LocalRelationship extends \Friendica\BaseEntity +{ + /** @var int */ + protected $userId; + /** @var int */ + protected $contactId; + /** @var bool */ + protected $blocked; + /** @var bool */ + protected $ignored; + /** @var bool */ + protected $collapsed; + /** @var bool */ + protected $hidden; + /** @var bool */ + protected $pending; + /** @var int */ + protected $rel; + /** @var string */ + protected $info; + /** @var bool */ + protected $notifyNewPosts; + /** @var bool */ + protected $isRemoteSelf; + /** @var int */ + protected $fetchFurtherInformation; + /** @var string */ + protected $ffiKeywordDenylist; + /** @var bool */ + protected $subhub; + /** @var string */ + protected $hubVerify; + /** @var string */ + protected $protocol; + /** @var int */ + protected $rating; + /** @var int */ + protected $priority; + + public function __construct(int $userId, int $contactId, bool $blocked = false, bool $ignored = false, bool $collapsed = false, bool $hidden = false, bool $pending = false, int $rel = Contact::NOTHING, string $info = '', bool $notifyNewPosts = false, bool $isRemoteSelf = false, int $fetchFurtherInformation = 0, string $ffiKeywordDenylist = '', bool $subhub = false, string $hubVerify = '', string $protocol = Protocol::PHANTOM, ?int $rating = null, ?int $priority = null) + { + $this->userId = $userId; + $this->contactId = $contactId; + $this->blocked = $blocked; + $this->ignored = $ignored; + $this->collapsed = $collapsed; + $this->hidden = $hidden; + $this->pending = $pending; + $this->rel = $rel; + $this->info = $info; + $this->notifyNewPosts = $notifyNewPosts; + $this->isRemoteSelf = $isRemoteSelf; + $this->fetchFurtherInformation = $fetchFurtherInformation; + $this->ffiKeywordDenylist = $ffiKeywordDenylist; + $this->subhub = $subhub; + $this->hubVerify = $hubVerify; + $this->protocol = $protocol; + $this->rating = $rating; + $this->priority = $priority; + } + + public function addFollow() + { + $this->rel = in_array($this->rel, [Contact::FOLLOWER, Contact::FRIEND]) ? Contact::FRIEND : Contact::SHARING; + } + + public function removeFollow() + { + $this->rel = in_array($this->rel, [Contact::FOLLOWER, Contact::FRIEND]) ? Contact::FOLLOWER : Contact::NOTHING; + } + + public function addFollower() + { + $this->rel = in_array($this->rel, [Contact::SHARING, Contact::FRIEND]) ? Contact::FRIEND : Contact::FOLLOWER; + } + + public function removeFollower() + { + $this->rel = in_array($this->rel, [Contact::SHARING, Contact::FRIEND]) ? Contact::SHARING : Contact::NOTHING; + } +} diff --git a/src/Contact/LocalRelationship/Exception/LocalRelationshipPersistenceException.php b/src/Contact/LocalRelationship/Exception/LocalRelationshipPersistenceException.php new file mode 100644 index 0000000000..78c5bc5f71 --- /dev/null +++ b/src/Contact/LocalRelationship/Exception/LocalRelationshipPersistenceException.php @@ -0,0 +1,11 @@ +. + * + */ + +namespace Friendica\Contact\LocalRelationship\Factory; + +use Friendica\BaseFactory; +use Friendica\Capabilities\ICanCreateFromTableRow; +use Friendica\Contact\LocalRelationship\Entity; +use Friendica\Core\Protocol; +use Friendica\Model\Contact; + +class LocalRelationship extends BaseFactory implements ICanCreateFromTableRow +{ + /** + * @inheritDoc + */ + public function createFromTableRow(array $row): Entity\LocalRelationship + { + return new Entity\LocalRelationship( + $row['uid'], + $row['cid'], + $row['blocked'] ?? false, + $row['ignored'] ?? false, + $row['collapsed'] ?? false, + $row['hidden'] ?? false, + $row['pending'] ?? false, + $row['rel'] ?? Contact::NOTHING, + $row['info'] ?? '', + $row['notify_new_posts'] ?? false, + $row['remote_self'] ?? false, + $row['fetch_further_information'] ?? 0, + $row['ffi_keyword_denylist'] ?? '', + $row['subhub'] ?? false, + $row['hub-verify'] ?? '', + $row['protocol'] ?? Protocol::PHANTOM, + $row['rating'] ?? null, + $row['priority'] ?? null + ); + } +} diff --git a/src/Contact/LocalRelationship/Repository/LocalRelationship.php b/src/Contact/LocalRelationship/Repository/LocalRelationship.php new file mode 100644 index 0000000000..4261d4c9a4 --- /dev/null +++ b/src/Contact/LocalRelationship/Repository/LocalRelationship.php @@ -0,0 +1,133 @@ +. + * + */ + +namespace Friendica\Contact\LocalRelationship\Repository; + +use Friendica\Contact\LocalRelationship\Entity; +use Friendica\Contact\LocalRelationship\Exception; +use Friendica\Contact\LocalRelationship\Factory; +use Friendica\Database\Database; +use Friendica\Network\HTTPException; +use Psr\Log\LoggerInterface; + +class LocalRelationship extends \Friendica\BaseRepository +{ + protected static $table_name = 'user-contact'; + + /** @var Factory\LocalRelationship */ + protected $factory; + + public function __construct(Database $database, LoggerInterface $logger, Factory\LocalRelationship $factory) + { + parent::__construct($database, $logger, $factory); + } + + /** + * @param int $uid + * @param int $cid + * @return Entity\LocalRelationship + * @throws HTTPException\NotFoundException + */ + public function selectForUserContact(int $uid, int $cid): Entity\LocalRelationship + { + return $this->_selectOne(['uid' => $uid, 'cid' => $cid]); + } + + /** + * Returns the existing local relationship between a user and a public contact or a default + * relationship if it doesn't. + * + * @param int $uid + * @param int $cid + * @return Entity\LocalRelationship + * @throws HTTPException\NotFoundException + */ + public function getForUserContact(int $uid, int $cid): Entity\LocalRelationship + { + try { + return $this->selectForUserContact($uid, $cid); + } catch (HTTPException\NotFoundException $e) { + return $this->factory->createFromTableRow(['uid' => $uid, 'cid' => $cid]); + } + } + + /** + * @param int $uid + * @param int $cid + * @return bool + * @throws \Exception + */ + public function existsForUserContact(int $uid, int $cid): bool + { + return $this->exists(['uid' => $uid, 'cid' => $cid]); + } + + /** + * Converts a given local relationship into a DB compatible row array + * + * @param Entity\LocalRelationship $localRelationship + * + * @return array + */ + protected function convertToTableRow(Entity\LocalRelationship $localRelationship): array + { + return [ + 'uid' => $localRelationship->userId, + 'cid' => $localRelationship->contactId, + 'uri-id' => $localRelationship->uriId, + 'blocked' => $localRelationship->blocked, + 'ignored' => $localRelationship->ignored, + 'collapsed' => $localRelationship->collapsed, + 'pending' => $localRelationship->pending, + 'rel' => $localRelationship->rel, + 'info' => $localRelationship->info, + 'notify_new_posts' => $localRelationship->notifyNewPosts, + 'remote_self' => $localRelationship->isRemoteSelf, + 'fetch_further_information' => $localRelationship->fetchFurtherInformation, + 'ffi_keyword_denylist' => $localRelationship->ffiKeywordDenylist, + 'subhub' => $localRelationship->subhub, + 'hub-verify' => $localRelationship->hubVerify, + 'protocol' => $localRelationship->protocol, + 'rating' => $localRelationship->rating, + 'priority' => $localRelationship->priority, + ]; + } + + /** + * @param Entity\LocalRelationship $localRelationship + * + * @return Entity\LocalRelationship + * + * @throws Exception\LocalRelationshipPersistenceException In case the underlying storage cannot save the LocalRelationship + */ + public function save(Entity\LocalRelationship $localRelationship): Entity\LocalRelationship + { + try { + $fields = $this->convertToTableRow($localRelationship); + + $this->db->insert(self::$table_name, $fields, Database::INSERT_UPDATE); + + return $localRelationship; + } catch (\Exception $exception) { + throw new Exception\LocalRelationshipPersistenceException(sprintf('Cannot insert/update the local relationship %d for user %d', $localRelationship->contactId, $localRelationship->userId), $exception); + } + } +}