X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FModule%2FContact.php;h=281e690086dee3073254a0fdd82db1872c2347cd;hb=c00da77c677c0b5d3d9c3391365530e41a4dad7c;hp=659380fbef3ba7bf3a08197bc923ff038fcdf2de;hpb=722aada460aa023212b7d97932fe338fe54861a8;p=friendica.git diff --git a/src/Module/Contact.php b/src/Module/Contact.php index 659380fbef..281e690086 100644 --- a/src/Module/Contact.php +++ b/src/Module/Contact.php @@ -1,6 +1,6 @@ $contacts_id, 'uid' => local_user(), 'self' => false, 'deleted' => false]); - $orig_records = DBA::toArray($stmt); + self::checkFormSecurityTokenRedirectOnError($redirectUrl, 'contact_batch_actions'); + + $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_archive']) - && self::archiveContact($contact_id, $orig_record) + + if (!empty($_POST['contacts_batch_drop']) && $cdata['user'] + && self::dropContact($cdata['user'], local_user()) ) { $count_actions++; } - if (!empty($_POST['contacts_batch_drop'])) { - self::dropContact($orig_record); - $count_actions++; - } } if ($count_actions > 0) { info(DI::l10n()->tt('%d contact edited.', '%d contacts edited.', $count_actions)); } - DI::baseUrl()->redirect('contact'); + DI::baseUrl()->redirect($redirectUrl); } public static function post(array $parameters = []) { - $a = DI::app(); - if (!local_user()) { return; } // @TODO: Replace with parameter from router - if ($a->argv[1] === 'batch') { + if (DI::args()->getArgv()[1] === 'batch') { self::batchActions(); return; } // @TODO: Replace with parameter from router - $contact_id = intval($a->argv[1]); + $contact_id = intval(DI::args()->getArgv()[1]); if (!$contact_id) { return; } @@ -131,6 +132,8 @@ class Contact extends BaseModule $fetch_further_information = intval($_POST['fetch_further_information'] ?? 0); + $remote_self = $_POST['remote_self'] ?? false; + $ffi_keyword_denylist = Strings::escapeHtml(trim($_POST['ffi_keyword_denylist'] ?? '')); $priority = intval($_POST['poll'] ?? 0); @@ -146,6 +149,7 @@ class Contact extends BaseModule 'hidden' => $hidden, 'notify_new_posts' => $notify, 'fetch_further_information' => $fetch_further_information, + 'remote_self' => $remote_self, 'ffi_keyword_denylist' => $ffi_keyword_denylist], ['id' => $contact_id, 'uid' => local_user()] ); @@ -153,18 +157,18 @@ class Contact extends BaseModule if (!DBA::isResult($r)) { notice(DI::l10n()->t('Failed to update contact record.')); } - - $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user(), 'deleted' => false]); - if (DBA::isResult($contact)) { - $a->data['contact'] = $contact; - } - return; } /* 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)) { @@ -172,21 +176,27 @@ class Contact extends BaseModule } if ($contact['network'] == Protocol::OSTATUS) { - $user = Model\User::getById($contact['uid']); - $result = Model\Contact::createFromProbe($user, $contact['url'], false, $contact['network']); + $result = Model\Contact::createFromProbeForUser($contact['uid'], $contact['url'], $contact['network']); if ($result['success']) { DBA::update('contact', ['subhub' => 1], ['id' => $contact_id]); } - } else { + // pull feed and consume it, which should subscribe to the hub. Worker::add(PRIORITY_HIGH, 'OnePoll', $contact_id, 'force'); + } else { + Worker::add(PRIORITY_HIGH, 'UpdateContact', $contact_id); } } - 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; } @@ -198,10 +208,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); @@ -210,41 +220,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); } /** - * Toggles the archived status of a contact identified by id. - * If the current status isn't provided, this will always archive the contact. - * - * @param $contact_id - * @param $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 \Exception + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws \ImagickException */ - private static function archiveContact($contact_id, $orig_record) + private static function dropContact(int $contact_id, int $uid): bool { - $archived = empty($orig_record['archive']); - $r = DBA::update('contact', ['archive' => $archived], ['id' => $contact_id, 'uid' => local_user()]); - - return DBA::isResult($r); - } + $contact = Model\Contact::getContactForUser($contact_id, $uid); + if (!DBA::isResult($contact)) { + return false; + } - private static function dropContact($orig_record) - { - $owner = Model\User::getOwnerDataById(local_user()); + $owner = Model\User::getOwnerDataById($uid); if (!DBA::isResult($owner)) { - return; + return false; } - Model\Contact::terminateFriendship($owner, $orig_record, true); - Model\Contact::remove($orig_record['id']); + Model\Contact::terminateFriendship($owner, $contact, true); + Model\Contact::remove($contact['id']); + + return true; } public static function content(array $parameters = [], $update = 0) @@ -260,6 +267,9 @@ class Contact extends BaseModule $rel = Strings::escapeTags(trim($_GET['rel'] ?? '')); $group = Strings::escapeTags(trim($_GET['group'] ?? '')); + $accounttype = $_GET['accounttype'] ?? ''; + $accounttypeid = User::getAccountTypeByString($accounttype); + $page = DI::page(); $page->registerFooterScript(Theme::getPathForFile('asset/typeahead.js/dist/typeahead.bundle.js')); @@ -269,76 +279,46 @@ class Contact extends BaseModule $contact = null; // @TODO: Replace with parameter from router - if ($a->argc == 2 && intval($a->argv[1]) - || $a->argc == 3 && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations']) + if (DI::args()->getArgc() == 2 && intval(DI::args()->getArgv()[1]) + || DI::args()->getArgc() == 3 && intval(DI::args()->getArgv()[1]) && in_array(DI::args()->getArgv()[2], ['posts', 'conversations']) ) { - $contact_id = intval($a->argv[1]); + $contact_id = intval(DI::args()->getArgv()[1]); // Ensure to use the user contact when the public contact was provided - $data = Model\Contact::getPublicAndUserContacID($contact_id, local_user()); + $data = Model\Contact::getPublicAndUserContactID($contact_id, local_user()); if (!empty($data['user']) && ($contact_id == $data['public'])) { $contact_id = $data['user']; } - $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => [0, local_user()], 'deleted' => false]); + if (!empty($data)) { + $contact = DBA::selectFirst('contact', [], [ + 'id' => $contact_id, + 'uid' => [0, local_user()], + 'deleted' => false + ]); - // Don't display contacts that are about to be deleted - if ($contact['network'] == Protocol::PHANTOM) { - $contact = false; + // Don't display contacts that are about to be deleted + if (DBA::isResult($contact) && !empty($contact['network']) && $contact['network'] == Protocol::PHANTOM) { + $contact = false; + } } } if (DBA::isResult($contact)) { if ($contact['self']) { // @TODO: Replace with parameter from router - if (($a->argc == 3) && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations'])) { + if ((DI::args()->getArgc() == 3) && intval(DI::args()->getArgv()[1]) && in_array(DI::args()->getArgv()[2], ['posts', 'conversations'])) { DI::baseUrl()->redirect('profile/' . $contact['nick']); } else { DI::baseUrl()->redirect('profile/' . $contact['nick'] . '/profile'); } } - $a->data['contact'] = $contact; - - if (($contact['network'] != '') && ($contact['network'] != Protocol::DFRN)) { - $network_link = Strings::formatNetworkName($contact['network'], $contact['url']); - } else { - $network_link = ''; - } - - $follow_link = ''; - $unfollow_link = ''; - if (in_array($contact['network'], Protocol::NATIVE_SUPPORT)) { - if ($contact['uid'] && in_array($contact['rel'], [Model\Contact::SHARING, Model\Contact::FRIEND])) { - $unfollow_link = 'unfollow?url=' . urlencode($contact['url']); - } elseif(!$contact['pending']) { - $follow_link = 'follow?url=' . urlencode($contact['url']); - } - } - - $wallmessage_link = ''; - if ($contact['uid'] && Model\Contact::canReceivePrivateMessages($contact)) { - $wallmessage_link = 'message/new/' . $contact['id']; - } - - $vcard_widget = Renderer::replaceMacros(Renderer::getMarkupTemplate('widget/vcard.tpl'), [ - '$name' => $contact['name'], - '$photo' => Model\Contact::getPhoto($contact), - '$url' => Model\Contact::magicLinkByContact($contact, $contact['url']), - '$addr' => $contact['addr'] ?? '', - '$network_link' => $network_link, - '$network' => DI::l10n()->t('Network:'), - '$account_type' => Model\Contact::getAccountType($contact), - '$follow' => DI::l10n()->t('Follow'), - '$follow_link' => $follow_link, - '$unfollow' => DI::l10n()->t('Unfollow'), - '$unfollow_link' => $unfollow_link, - '$wallmessage' => DI::l10n()->t('Message'), - '$wallmessage_link' => $wallmessage_link, - ]); + $vcard_widget = Widget\VCard::getHTML($contact); $findpeople_widget = ''; $follow_widget = ''; + $account_widget = ''; $networks_widget = ''; $rel_widget = ''; @@ -356,12 +336,13 @@ class Contact extends BaseModule $follow_widget = Widget::follow(); } + $account_widget = Widget::accounttypes($_SERVER['REQUEST_URI'], $accounttype); $networks_widget = Widget::networks($_SERVER['REQUEST_URI'], $nets); $rel_widget = Widget::contactRels($_SERVER['REQUEST_URI'], $rel); $groups_widget = Widget::groups($_SERVER['REQUEST_URI'], $group); } - DI::page()['aside'] .= $vcard_widget . $findpeople_widget . $follow_widget . $groups_widget . $networks_widget . $rel_widget; + DI::page()['aside'] .= $vcard_widget . $findpeople_widget . $follow_widget . $account_widget . $groups_widget . $networks_widget . $rel_widget; $tpl = Renderer::getMarkupTemplate('contacts-head.tpl'); DI::page()['htmlhead'] .= Renderer::replaceMacros($tpl, [ @@ -376,64 +357,76 @@ class Contact extends BaseModule return Login::form(); } - if ($a->argc == 3) { - $contact_id = intval($a->argv[1]); + if (DI::args()->getArgc() == 3) { + $contact_id = intval(DI::args()->getArgv()[1]); if (!$contact_id) { throw new BadRequestException(); } // @TODO: Replace with parameter from router - $cmd = $a->argv[2]; + $cmd = DI::args()->getArgv()[2]; $orig_record = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => [0, local_user()], 'self' => false, 'deleted' => false]); if (!DBA::isResult($orig_record)) { 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); + if ($cmd === 'posts') { + return self::getPostsHTML($a, $contact_id); + } + + if ($cmd === 'conversations') { + return self::getConversationsHMTL($a, $contact_id, $update); + } + + self::checkFormSecurityTokenRedirectOnError('contact/' . $contact_id, 'contact_action', 't'); + + $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') { - self::blockContact($contact_id); + if (public_contact() === $cdata['public']) { + throw new BadRequestException(DI::l10n()->t('You can\'t block yourself')); + } + + 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') { - self::ignoreContact($contact_id); - - $ignored = Model\Contact\User::isIgnored($contact_id, local_user()); - info(($ignored ? DI::l10n()->t('Contact has been ignored') : DI::l10n()->t('Contact has been unignored'))); + if (public_contact() === $cdata['public']) { + throw new BadRequestException(DI::l10n()->t('You can\'t ignore yourself')); + } - DI::baseUrl()->redirect('contact/' . $contact_id); - // NOTREACHED - } + self::toggleIgnoreContact($cdata['public']); - if ($cmd === 'archive' && ($orig_record['uid'] != 0)) { - $r = self::archiveContact($contact_id, $orig_record); - if ($r) { - $archived = (($orig_record['archive']) ? 0 : 1); - info((($archived) ? DI::l10n()->t('Contact has been archived') : DI::l10n()->t('Contact has been unarchived'))); - } + $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'] = ''; @@ -445,7 +438,8 @@ class Contact extends BaseModule '$message' => DI::l10n()->t('Do you really want to delete this contact?'), '$confirm' => DI::l10n()->t('Yes'), '$confirm_url' => DI::args()->getCommand(), - '$confirm_name' => 'confirmed', + '$confirm_name' => 't', + '$confirm_value' => BaseModule::getFormSecurityToken('contact_action'), '$cancel' => DI::l10n()->t('Cancel'), ]); } @@ -454,25 +448,18 @@ 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 } - if ($cmd === 'posts') { - return self::getPostsHTML($a, $contact_id); - } - if ($cmd === 'conversations') { - return self::getConversationsHMTL($a, $contact_id, $update); - } } $_SESSION['return_path'] = DI::args()->getQueryString(); - if (!empty($a->data['contact']) && is_array($a->data['contact'])) { - $contact = $a->data['contact']; - + if (!empty($contact)) { DI::page()['htmlhead'] .= Renderer::replaceMacros(Renderer::getMarkupTemplate('contact_head.tpl'), [ '$baseurl' => DI::baseUrl()->get(true), ]); @@ -508,7 +495,7 @@ class Contact extends BaseModule $relation_text = sprintf($relation_text, $contact['name']); - $url = Model\Contact::magicLink($contact['url']); + $url = Model\Contact::magicLinkByContact($contact); if (strpos($url, 'redir/') === 0) { $sparkle = ' class="sparkle" '; } else { @@ -520,13 +507,13 @@ class Contact extends BaseModule $last_update = (($contact['last-update'] <= DBA::NULL_DATETIME) ? DI::l10n()->t('Never') : DateTimeFormat::local($contact['last-update'], 'D, j M Y, g:i A')); if ($contact['last-update'] > DBA::NULL_DATETIME) { - $last_update .= ' ' . (($contact['last-update'] <= $contact['success_update']) ? DI::l10n()->t('(Update was successful)') : DI::l10n()->t('(Update was not successful)')); + $last_update .= ' ' . ($contact['failed'] ? DI::l10n()->t('(Update was not successful)') : DI::l10n()->t('(Update was successful)')); } $lblsuggest = (($contact['network'] === Protocol::DFRN) ? DI::l10n()->t('Suggest friends') : ''); $poll_enabled = in_array($contact['network'], [Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]); - $nettype = DI::l10n()->t('Network type: %s', ContactSelector::networkToName($contact['network'], $contact['url'], $contact['protocol'])); + $nettype = DI::l10n()->t('Network type: %s', ContactSelector::networkToName($contact['network'], $contact['url'], $contact['protocol'], $contact['gsid'])); // tabs $tab_str = self::getTabsHTML($contact, self::TAB_PROFILE); @@ -549,8 +536,30 @@ class Contact extends BaseModule ]; } + // Disable remote self for everything except feeds. + // There is an issue when you repeat an item from maybe twitter and you got comments from friendica and twitter + // Problem is, you couldn't reply to both networks. + $allow_remote_self = in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::FEED, Protocol::DFRN, Protocol::DIASPORA, Protocol::TWITTER]) + && DI::config()->get('system', 'allow_users_remote_self'); + + if ($contact['network'] == Protocol::FEED) { + $remote_self_options = [Model\Contact::MIRROR_DEACTIVATED => DI::l10n()->t('No mirroring'), + Model\Contact::MIRROR_FORWARDED => DI::l10n()->t('Mirror as forwarded posting'), + Model\Contact::MIRROR_OWN_POST => DI::l10n()->t('Mirror as my own posting')]; + } elseif (in_array($contact['network'], [Protocol::ACTIVITYPUB])) { + $remote_self_options = [Model\Contact::MIRROR_DEACTIVATED => DI::l10n()->t('No mirroring'), + Model\Contact::MIRROR_NATIVE_RESHARE => DI::l10n()->t('Native reshare')]; + } elseif (in_array($contact['network'], [Protocol::DFRN])) { + $remote_self_options = [Model\Contact::MIRROR_DEACTIVATED => DI::l10n()->t('No mirroring'), + Model\Contact::MIRROR_OWN_POST => DI::l10n()->t('Mirror as my own posting'), + Model\Contact::MIRROR_NATIVE_RESHARE => DI::l10n()->t('Native reshare')]; + } else { + $remote_self_options = [Model\Contact::MIRROR_DEACTIVATED => DI::l10n()->t('No mirroring'), + Model\Contact::MIRROR_OWN_POST => DI::l10n()->t('Mirror as my own posting')]; + } + $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); } @@ -610,11 +619,13 @@ class Contact extends BaseModule '$profileurllabel'=> DI::l10n()->t('Profile URL'), '$profileurl' => $contact['url'], '$account_type' => Model\Contact::getAccountType($contact), - '$location' => BBCode::convert($contact['location']), + '$location' => BBCode::convertForUriId($contact['uri-id'] ?? 0, $contact['location']), '$location_label' => DI::l10n()->t('Location:'), - '$xmpp' => BBCode::convert($contact['xmpp']), + '$xmpp' => BBCode::convertForUriId($contact['uri-id'] ?? 0, $contact['xmpp']), '$xmpp_label' => DI::l10n()->t('XMPP:'), - '$about' => BBCode::convert($contact['about'], false), + '$matrix' => BBCode::convertForUriId($contact['uri-id'] ?? 0, $contact['matrix']), + '$matrix_label' => DI::l10n()->t('Matrix:'), + '$about' => BBCode::convertForUriId($contact['uri-id'] ?? 0, $contact['about'], BBCode::EXTERNAL), '$about_label' => DI::l10n()->t('About:'), '$keywords' => $contact['keywords'], '$keywords_label' => DI::l10n()->t('Tags:'), @@ -623,6 +634,13 @@ class Contact extends BaseModule '$contact_status' => DI::l10n()->t('Status'), '$contact_settings_label' => $contact_settings_label, '$contact_profile_label' => DI::l10n()->t('Profile'), + '$allow_remote_self' => $allow_remote_self, + '$remote_self' => ['remote_self', + DI::l10n()->t('Mirror postings from this contact'), + $contact['remote_self'], + DI::l10n()->t('Mark this contact as remote_self, this will cause friendica to repost new entries from this contact.'), + $remote_self_options + ], ]); $arr = ['contact' => $contact, 'output' => $o]; @@ -635,7 +653,7 @@ class Contact extends BaseModule $sql_values = [local_user()]; // @TODO: Replace with parameter from router - $type = $a->argv[1] ?? ''; + $type = DI::args()->getArgv()[1] ?? ''; switch ($type) { case 'blocked': @@ -655,7 +673,7 @@ class Contact extends BaseModule $sql_extra = " AND `archive` AND NOT `blocked` AND NOT `pending`"; break; case 'pending': - $sql_extra = " AND `pending` AND NOT `archive` AND ((`rel` = ?) + $sql_extra = " AND `pending` AND NOT `archive` AND NOT `failed` AND ((`rel` = ?) OR EXISTS (SELECT `id` FROM `intro` WHERE `contact-id` = `contact`.`id` AND NOT `ignore`))"; $sql_values[] = Model\Contact::SHARING; break; @@ -664,6 +682,11 @@ class Contact extends BaseModule break; } + if (isset($accounttypeid)) { + $sql_extra .= " AND `contact-type` = ?"; + $sql_values[] = $accounttypeid; + } + $searching = false; $search_hdr = null; if ($search) { @@ -832,13 +855,13 @@ class Contact extends BaseModule '$submit' => DI::l10n()->t('Find'), '$cmd' => DI::args()->getCommand(), '$contacts' => $contacts, + '$form_security_token' => BaseModule::getFormSecurityToken('contact_batch_actions'), '$contact_drop_confirm' => DI::l10n()->t('Do you really want to delete this contact?'), 'multiselect' => 1, '$batch_actions' => [ 'contacts_batch_update' => DI::l10n()->t('Update'), 'contacts_batch_block' => DI::l10n()->t('Block') . '/' . DI::l10n()->t('Unblock'), 'contacts_batch_ignore' => DI::l10n()->t('Ignore') . '/' . DI::l10n()->t('Unignore'), - 'contacts_batch_archive' => DI::l10n()->t('Archive') . '/' . DI::l10n()->t('Unarchive'), 'contacts_batch_drop' => DI::l10n()->t('Delete'), ], '$h_batch_actions' => DI::l10n()->t('Batch Actions'), @@ -863,7 +886,7 @@ class Contact extends BaseModule public static function getTabsHTML(array $contact, int $active_tab) { $cid = $pcid = $contact['id']; - $data = Model\Contact::getPublicAndUserContacID($contact['id'], local_user()); + $data = Model\Contact::getPublicAndUserContactID($contact['id'], local_user()); if (!empty($data['user']) && ($contact['id'] == $data['public'])) { $cid = $data['user']; } elseif (!empty($data['public'])) { @@ -905,7 +928,7 @@ class Contact extends BaseModule ], ]; - if ($cid != $pcid) { + if (!empty($contact['network']) && in_array($contact['network'], [Protocol::FEED, Protocol::MAIL]) && ($cid != $pcid)) { $tabs[] = ['label' => DI::l10n()->t('Advanced'), 'url' => 'contact/' . $cid . '/advanced/', 'sel' => (($active_tab == self::TAB_ADVANCED) ? 'active' : ''), @@ -921,25 +944,14 @@ class Contact extends BaseModule return $tab_str; } - private static function getConversationsHMTL($a, $contact_id, $update) + public static function getConversationsHMTL($a, $contact_id, $update, $parent = 0) { $o = ''; if (!$update) { // We need the editor here to be able to reshare an item. if (local_user()) { - $x = [ - 'is_owner' => true, - 'allow_location' => $a->user['allow_location'], - 'default_location' => $a->user['default-location'], - 'nickname' => $a->user['nickname'], - 'lockstate' => (is_array($a->user) && (strlen($a->user['allow_cid']) || strlen($a->user['allow_gid']) || strlen($a->user['deny_cid']) || strlen($a->user['deny_gid'])) ? 'lock' : 'unlock'), - 'acl' => ACL::getFullSelectorHTML(DI::page(), $a->user, true), - 'bang' => '', - 'visitor' => 'block', - 'profile_uid' => local_user(), - ]; - $o = status_editor($a, $x, 0, true); + $o = status_editor($a, [], 0, true); } } @@ -950,16 +962,17 @@ class Contact extends BaseModule } if (DBA::isResult($contact)) { - DI::page()['aside'] = ''; - - $profiledata = Model\Contact::getByURLForUser($contact['url'], local_user()); - - Model\Profile::load($a, '', $profiledata, true); + if (!$update) { + $profiledata = Model\Contact::getByURLForUser($contact['url'], local_user()); + DI::page()['aside'] = Widget\VCard::getHTML($profiledata); + } else { + DI::page()['aside'] = ''; + } if ($contact['uid'] == 0) { - $o .= Model\Contact::getPostsFromId($contact['id'], true, $update); + $o .= Model\Contact::getPostsFromId($contact['id'], true, $update, $parent); } else { - $o .= Model\Contact::getPostsFromUrl($contact['url'], true, $update); + $o .= Model\Contact::getPostsFromUrl($contact['url'], true, $update, $parent); } } @@ -973,15 +986,13 @@ class Contact extends BaseModule $o = self::getTabsHTML($contact, self::TAB_POSTS); if (DBA::isResult($contact)) { - DI::page()['aside'] = ''; - $profiledata = Model\Contact::getByURLForUser($contact['url'], local_user()); if (local_user() && in_array($profiledata['network'], Protocol::FEDERATED)) { $profiledata['remoteconnect'] = DI::baseUrl() . '/follow?url=' . urlencode($profiledata['url']); } - Model\Profile::load($a, '', $profiledata, true); + DI::page()['aside'] = Widget\VCard::getHTML($profiledata); if ($contact['uid'] == 0) { $o .= Model\Contact::getPostsFromId($contact['id']); @@ -1031,7 +1042,7 @@ class Contact extends BaseModule } } - $url = Model\Contact::magicLink($contact['url']); + $url = Model\Contact::magicLinkByContact($contact); if (strpos($url, 'redir/') === 0) { $sparkle = ' class="sparkle" '; @@ -1058,24 +1069,24 @@ class Contact extends BaseModule 'url' => $url, 'img_hover' => DI::l10n()->t('Visit %s\'s profile [%s]', $contact['name'], $contact['url']), 'photo_menu' => Model\Contact::photoMenu($contact), - 'thumb' => Model\Contact::getThumb($contact), + 'thumb' => Model\Contact::getThumb($contact, true), 'alt_text' => $alt_text, 'name' => $contact['name'], 'nick' => $contact['nick'], - 'details' => $contact['location'], + 'details' => $contact['location'], 'tags' => $contact['keywords'], 'about' => $contact['about'], 'account_type' => Model\Contact::getAccountType($contact), 'sparkle' => $sparkle, 'itemurl' => ($contact['addr'] ?? '') ?: $contact['url'], - 'network' => ContactSelector::networkToName($contact['network'], $contact['url'], $contact['protocol']), + 'network' => ContactSelector::networkToName($contact['network'], $contact['url'], $contact['protocol'], $contact['gsid']), ]; } /** * 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 @@ -1085,6 +1096,8 @@ class Contact extends BaseModule $poll_enabled = in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]); $contact_actions = []; + $formSecurityToken = self::getFormSecurityToken('contact_action'); + // Provide friend suggestion only for Friendica contacts if ($contact['network'] === Protocol::DFRN) { $contact_actions['suggest'] = [ @@ -1099,17 +1112,17 @@ class Contact extends BaseModule if ($poll_enabled) { $contact_actions['update'] = [ 'label' => DI::l10n()->t('Update now'), - 'url' => 'contact/' . $contact['id'] . '/update', + 'url' => 'contact/' . $contact['id'] . '/update?t=' . $formSecurityToken, 'title' => '', 'sel' => '', 'id' => 'update', ]; } - if (in_array($contact['network'], Protocol::FEDERATED)) { + if (in_array($contact['network'], Protocol::NATIVE_SUPPORT)) { $contact_actions['updateprofile'] = [ 'label' => DI::l10n()->t('Refetch contact data'), - 'url' => 'contact/' . $contact['id'] . '/updateprofile', + 'url' => 'contact/' . $contact['id'] . '/updateprofile?t=' . $formSecurityToken, 'title' => '', 'sel' => '', 'id' => 'updateprofile', @@ -1118,7 +1131,7 @@ class Contact extends BaseModule $contact_actions['block'] = [ 'label' => (intval($contact['blocked']) ? DI::l10n()->t('Unblock') : DI::l10n()->t('Block')), - 'url' => 'contact/' . $contact['id'] . '/block', + 'url' => 'contact/' . $contact['id'] . '/block?t=' . $formSecurityToken, 'title' => DI::l10n()->t('Toggle Blocked status'), 'sel' => (intval($contact['blocked']) ? 'active' : ''), 'id' => 'toggle-block', @@ -1126,24 +1139,16 @@ class Contact extends BaseModule $contact_actions['ignore'] = [ 'label' => (intval($contact['readonly']) ? DI::l10n()->t('Unignore') : DI::l10n()->t('Ignore')), - 'url' => 'contact/' . $contact['id'] . '/ignore', + 'url' => 'contact/' . $contact['id'] . '/ignore?t=' . $formSecurityToken, 'title' => DI::l10n()->t('Toggle Ignored status'), 'sel' => (intval($contact['readonly']) ? 'active' : ''), 'id' => 'toggle-ignore', ]; if ($contact['uid'] != 0) { - $contact_actions['archive'] = [ - 'label' => (intval($contact['archive']) ? DI::l10n()->t('Unarchive') : DI::l10n()->t('Archive')), - 'url' => 'contact/' . $contact['id'] . '/archive', - 'title' => DI::l10n()->t('Toggle Archive status'), - 'sel' => (intval($contact['archive']) ? 'active' : ''), - 'id' => 'toggle-archive', - ]; - $contact_actions['delete'] = [ 'label' => DI::l10n()->t('Delete'), - 'url' => 'contact/' . $contact['id'] . '/drop', + 'url' => 'contact/' . $contact['id'] . '/drop?t=' . $formSecurityToken, 'title' => DI::l10n()->t('Delete contact'), 'sel' => '', 'id' => 'delete',