From d20b53607d8c71f9dfc78d6151ade21dcd1da3b0 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 5 Sep 2021 14:52:04 -0400 Subject: [PATCH] Distinguish between public and private contact in contact actions - Block and ignore is done relating to a public contact (uid = 0) - Update and drop is done relating to a private contact (uid !=0) - Method documentation has been improved to precise the contact type it needs - Public and private contact ids are retrieved before acting on contacts --- src/Module/Contact.php | 120 ++++++++++++++++++++++++++--------------- 1 file changed, 78 insertions(+), 42 deletions(-) diff --git a/src/Module/Contact.php b/src/Module/Contact.php index bfed6495a..6f32356a3 100644 --- a/src/Module/Contact.php +++ b/src/Module/Contact.php @@ -59,28 +59,33 @@ class Contact extends BaseModule return; } - $contacts_id = $_POST['contact_batch']; - - $stmt = DBA::select('contact', ['id', 'archive'], ['id' => $contacts_id, 'uid' => local_user(), 'self' => false, 'deleted' => false]); - $orig_records = DBA::toArray($stmt); + $orig_records = Model\Contact::selectToArray(['id', 'uid'], ['id' => $_POST['contact_batch'], 'uid' => [0, local_user()], 'self' => false, 'deleted' => false]); $count_actions = 0; foreach ($orig_records as $orig_record) { - $contact_id = $orig_record['id']; - if (!empty($_POST['contacts_batch_update'])) { - self::updateContactFromPoll($contact_id); + $cdata = Model\Contact::getPublicAndUserContactID($orig_record['id'], local_user()); + if (empty($cdata)) { + continue; + } + + if (!empty($_POST['contacts_batch_update']) && $cdata['user']) { + self::updateContactFromPoll($cdata['user']); $count_actions++; } + if (!empty($_POST['contacts_batch_block'])) { - self::blockContact($contact_id); + self::toggleBlockContact($cdata['public']); $count_actions++; } + if (!empty($_POST['contacts_batch_ignore'])) { - self::ignoreContact($contact_id); + self::toggleIgnoreContact($cdata['public']); $count_actions++; } - if (!empty($_POST['contacts_batch_drop'])) { - self::dropContact($orig_record); + + if (!empty($_POST['contacts_batch_drop']) && $cdata['user'] + && self::dropContact($cdata['user'], local_user()) + ) { $count_actions++; } } @@ -153,7 +158,13 @@ class Contact extends BaseModule /* contact actions */ - private static function updateContactFromPoll($contact_id) + /** + * @param int $contact_id Id of contact with uid != 0 + * @throws NotFoundException + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws \ImagickException + */ + private static function updateContactFromPoll(int $contact_id) { $contact = DBA::selectFirst('contact', ['uid', 'url', 'network'], ['id' => $contact_id, 'uid' => local_user(), 'deleted' => false]); if (!DBA::isResult($contact)) { @@ -174,9 +185,14 @@ class Contact extends BaseModule } } - private static function updateContactFromProbe($contact_id) + /** + * @param int $contact_id Id of the contact with uid != 0 + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws \ImagickException + */ + private static function updateContactFromProbe(int $contact_id) { - $contact = DBA::selectFirst('contact', ['url'], ['id' => $contact_id, 'uid' => [0, local_user()], 'deleted' => false]); + $contact = DBA::selectFirst('contact', ['url'], ['id' => $contact_id, 'uid' => local_user(), 'deleted' => false]); if (!DBA::isResult($contact)) { return; } @@ -188,10 +204,10 @@ class Contact extends BaseModule /** * Toggles the blocked status of a contact identified by id. * - * @param $contact_id + * @param int $contact_id Id of the contact with uid = 0 * @throws \Exception */ - private static function blockContact($contact_id) + private static function toggleBlockContact(int $contact_id) { $blocked = !Model\Contact\User::isBlocked($contact_id, local_user()); Model\Contact\User::setBlocked($contact_id, local_user(), $blocked); @@ -200,24 +216,38 @@ class Contact extends BaseModule /** * Toggles the ignored status of a contact identified by id. * - * @param $contact_id + * @param int $contact_id Id of the contact with uid = 0 * @throws \Exception */ - private static function ignoreContact($contact_id) + private static function toggleIgnoreContact(int $contact_id) { $ignored = !Model\Contact\User::isIgnored($contact_id, local_user()); Model\Contact\User::setIgnored($contact_id, local_user(), $ignored); } - private static function dropContact($orig_record) + /** + * @param int $contact_id Id for contact with uid != 0 + * @param int $uid Id for user we want to drop the contact for + * @return bool + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws \ImagickException + */ + private static function dropContact(int $contact_id, int $uid): bool { - $owner = Model\User::getOwnerDataById(local_user()); - if (!DBA::isResult($owner)) { - return; + $contact = Model\Contact::getContactForUser($contact_id, $uid); + if (!DBA::isResult($contact)) { + return false; } - Model\Contact::terminateFriendship($owner, $orig_record, true); - Model\Contact::remove($orig_record['id']); + $owner = Model\User::getOwnerDataById($uid); + if (!DBA::isResult($owner)) { + return false; + } + + Model\Contact::terminateFriendship($owner, $contact, true); + Model\Contact::remove($contact['id']); + + return true; } public static function content(array $parameters = [], $update = 0) @@ -331,47 +361,52 @@ class Contact extends BaseModule throw new NotFoundException(DI::l10n()->t('Contact not found')); } - if ($cmd === 'update' && ($orig_record['uid'] != 0)) { - self::updateContactFromPoll($contact_id); - DI::baseUrl()->redirect('contact/' . $contact_id); + $cdata = Model\Contact::getPublicAndUserContactID($orig_record['id'], local_user()); + if (empty($cdata)) { + throw new NotFoundException(DI::l10n()->t('Contact not found')); + } + + if ($cmd === 'update' && $cdata['user']) { + self::updateContactFromPoll($cdata['user']); + DI::baseUrl()->redirect('contact/' . $cdata['public']); // NOTREACHED } - if ($cmd === 'updateprofile') { - self::updateContactFromProbe($contact_id); - DI::baseUrl()->redirect('contact/' . $contact_id); + if ($cmd === 'updateprofile' && $cdata['user']) { + self::updateContactFromProbe($cdata['user']); + DI::baseUrl()->redirect('contact/' . $cdata['public']); // NOTREACHED } if ($cmd === 'block') { - if (public_contact() === $contact_id) { + if (public_contact() === $cdata['public']) { throw new BadRequestException(DI::l10n()->t('You can\'t block yourself')); } - self::blockContact($contact_id); + self::toggleBlockContact($cdata['public']); $blocked = Model\Contact\User::isBlocked($contact_id, local_user()); info(($blocked ? DI::l10n()->t('Contact has been blocked') : DI::l10n()->t('Contact has been unblocked'))); - DI::baseUrl()->redirect('contact/' . $contact_id); + DI::baseUrl()->redirect('contact/' . $cdata['public']); // NOTREACHED } if ($cmd === 'ignore') { - if (public_contact() === $contact_id) { + if (public_contact() === $cdata['public']) { throw new BadRequestException(DI::l10n()->t('You can\'t ignore yourself')); } - self::ignoreContact($contact_id); + self::toggleIgnoreContact($cdata['public']); - $ignored = Model\Contact\User::isIgnored($contact_id, local_user()); + $ignored = Model\Contact\User::isIgnored($cdata['public'], local_user()); info(($ignored ? DI::l10n()->t('Contact has been ignored') : DI::l10n()->t('Contact has been unignored'))); - DI::baseUrl()->redirect('contact/' . $contact_id); + DI::baseUrl()->redirect('contact/' . $cdata['public']); // NOTREACHED } - if ($cmd === 'drop' && ($orig_record['uid'] != 0)) { + if ($cmd === 'drop' && $cdata['user']) { // Check if we should do HTML-based delete confirmation if (!empty($_REQUEST['confirm'])) { DI::page()['aside'] = ''; @@ -392,8 +427,9 @@ class Contact extends BaseModule DI::baseUrl()->redirect('contact'); } - self::dropContact($orig_record); - info(DI::l10n()->t('Contact has been removed.')); + if (self::dropContact($cdata['user'], local_user())) { + info(DI::l10n()->t('Contact has been removed.')); + } DI::baseUrl()->redirect('contact'); // NOTREACHED @@ -508,7 +544,7 @@ class Contact extends BaseModule } $poll_interval = null; - if ((($contact['network'] == Protocol::FEED) && !DI::config()->get('system', 'adjust_poll_frequency')) || ($contact['network']== Protocol::MAIL)) { + if ((($contact['network'] == Protocol::FEED) && !DI::config()->get('system', 'adjust_poll_frequency')) || ($contact['network'] == Protocol::MAIL)) { $poll_interval = ContactSelector::pollInterval($contact['priority'], !$poll_enabled); } @@ -1034,7 +1070,7 @@ class Contact extends BaseModule /** * Gives a array with actions which can performed to a given contact * - * This includes actions like e.g. 'block', 'hide', 'archive', 'delete' and others + * This includes actions like e.g. 'block', 'hide', 'delete' and others * * @param array $contact Data about the Contact * @return array with contact related actions