page, 'aside')) { $a->page['aside'] = ''; } $contact_id = null; $contact = null; if ($a->argc == 2 && intval($a->argv[1]) || $a->argc == 3 && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations']) ) { $contact_id = intval($a->argv[1]); $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user()]); if (!DBA::isResult($contact)) { $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => 0]); } // Don't display contacts that are about to be deleted if ($contact['network'] == Protocol::PHANTOM) { $contact = false; } } if (DBA::isResult($contact)) { if ($contact['self']) { if (($a->argc == 3) && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations'])) { $a->redirect('profile/' . $contact['nick']); } else { $a->redirect('profile/' . $contact['nick'] . '?tab=profile'); } } $a->data['contact'] = $contact; if (($contact['network'] != '') && ($contact['network'] != Protocol::DFRN)) { $networkname = format_network_name($contact['network'], $contact['url']); } else { $networkname = ''; } /// @TODO Add nice spaces $vcard_widget = replace_macros(get_markup_template('vcard-widget.tpl'), [ '$name' => htmlentities($contact['name']), '$photo' => $contact['photo'], '$url' => Model\Contact::MagicLink($contact['url']), '$addr' => defaults($contact, 'addr', ''), '$network_name' => $networkname, '$network' => L10n::t('Network:'), '$account_type' => Model\Contact::getAccountType($contact) ]); $findpeople_widget = ''; $follow_widget = ''; $networks_widget = ''; } else { $vcard_widget = ''; $networks_widget = Widget::networks('contact', $nets); if (isset($_GET['add'])) { $follow_widget = Widget::follow($_GET['add']); } else { $follow_widget = Widget::follow(); } $findpeople_widget = Widget::findPeople(); } if ($contact['uid'] != 0) { $groups_widget = Model\Group::sidebarWidget('contact', 'group', 'full', 'everyone', $contact_id); } else { $groups_widget = null; } $a->page['aside'] .= replace_macros(get_markup_template('contacts-widget-sidebar.tpl'), [ '$vcard_widget' => $vcard_widget, '$findpeople_widget' => $findpeople_widget, '$follow_widget' => $follow_widget, '$groups_widget' => $groups_widget, '$networks_widget' => $networks_widget ]); $base = $a->getBaseURL(); $tpl = get_markup_template('contacts-head.tpl'); $a->page['htmlhead'] .= replace_macros($tpl, [ '$baseurl' => System::baseUrl(true), '$base' => $base ]); } private static function batchActions(App $a) { if (empty($_POST['contact_batch']) || !is_array($_POST['contact_batch'])) { return; } $contacts_id = $_POST['contact_batch']; $stmt = DBA::select('contact', ['id'], ['id' => $contacts_id, 'uid' => local_user(), 'self' => false]); $orig_records = DBA::toArray($stmt); $count_actions = 0; foreach ($orig_records as $orig_record) { $contact_id = $orig_record['id']; if (!empty($_POST['contacts_batch_update'])) { self::updateContactFromPoll($contact_id); $count_actions++; } if (!empty($_POST['contacts_batch_block'])) { self::blockContact($contact_id); $count_actions++; } if (!empty($_POST['contacts_batch_ignore'])) { self::ignoreContact($contact_id); $count_actions++; } if (!empty($_POST['contacts_batch_archive']) && self::archiveContact($contact_id, $orig_record) ) { $count_actions++; } if (!empty($_POST['contacts_batch_drop'])) { self::dropContact($orig_record); $count_actions++; } } if ($count_actions > 0) { info(L10n::tt('%d contact edited.', '%d contacts edited.', $count_actions)); } $a->redirect('contact'); } public static function post() { $a = self::getApp(); if (!local_user()) { return; } if ($a->argv[1] === 'batch') { self::batchActions($a); return; } $contact_id = intval($a->argv[1]); if (!$contact_id) { return; } if (!DBA::exists('contact', ['id' => $contact_id, 'uid' => local_user()])) { notice(L10n::t('Could not access contact record.') . EOL); $a->redirect('contact'); return; // NOTREACHED } Addon::callHooks('contact_edit_post', $_POST); $profile_id = intval(defaults($_POST, 'profile-assign', 0)); if ($profile_id) { if (!DBA::exists('profile', ['id' => $profile_id, 'uid' => local_user()])) { notice(L10n::t('Could not locate selected profile.') . EOL); return; } } $hidden = !empty($_POST['hidden']); $notify = !empty($_POST['notify']); $fetch_further_information = intval(defaults($_POST, 'fetch_further_information', 0)); $ffi_keyword_blacklist = escape_tags(trim(defaults($_POST, 'ffi_keyword_blacklist', ''))); $priority = intval(defaults($_POST, 'poll', 0)); if ($priority > 5 || $priority < 0) { $priority = 0; } $info = escape_tags(trim($_POST['info'])); $r = DBA::update('contact', [ 'profile-id' => $profile_id, 'priority' => $priority, 'info' => $info, 'hidden' => $hidden, 'notify_new_posts' => $notify, 'fetch_further_information' => $fetch_further_information, 'ffi_keyword_blacklist' => $ffi_keyword_blacklist], ['id' => $contact_id, 'uid' => local_user()] ); if (DBA::isResult($r)) { info(L10n::t('Contact updated.') . EOL); } else { notice(L10n::t('Failed to update contact record.') . EOL); } $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user()]); if (DBA::isResult($contact)) { $a->data['contact'] = $contact; } return; } /* contact actions */ private static function updateContactFromPoll($contact_id) { $contact = DBA::selectFirst('contact', ['uid', 'url', 'network'], ['id' => $contact_id, 'uid' => local_user()]); if (!DBA::isResult($contact)) { return; } $uid = $contact['uid']; if ($contact['network'] == Protocol::OSTATUS) { $result = Model\Contact::createFromProbe($uid, $contact['url'], false, $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'); } } private static function updateContactFromProbe($contact_id) { $contact = DBA::selectFirst('contact', ['uid', 'url', 'network'], ['id' => $contact_id, 'uid' => local_user()]); if (!DBA::isResult($contact)) { return; } $uid = $contact['uid']; $data = Probe::uri($contact['url'], '', 0, false); // 'Feed' or 'Unknown' is mostly a sign of communication problems if ((in_array($data['network'], [Protocol::FEED, Protocol::PHANTOM])) && ($data['network'] != $contact['network'])) { return; } $updatefields = ['name', 'nick', 'url', 'addr', 'batch', 'notify', 'poll', 'request', 'confirm', 'poco', 'network', 'alias']; $fields = []; if ($data['network'] == Protocol::OSTATUS) { $result = Model\Contact::createFromProbe($uid, $data['url'], false); if ($result['success']) { $fields['subhub'] = true; } } foreach ($updatefields AS $field) { if (!empty($data[$field])) { $fields[$field] = $data[$field]; } } $fields['nurl'] = normalise_link($data['url']); if (!empty($data['priority'])) { $fields['priority'] = intval($data['priority']); } if (empty($fields)) { return; } $r = DBA::update('contact', $fields, ['id' => $contact_id, 'uid' => local_user()]); // Update the entry in the contact table Model\Contact::updateAvatar($data['photo'], local_user(), $contact_id, true); // Update the entry in the gcontact table Model\GContact::updateFromProbe($data['url']); } private static function blockContact($contact_id) { $blocked = !Model\Contact::isBlockedByUser($contact_id, local_user()); Model\Contact::setBlockedForUser($contact_id, local_user(), $blocked); } private static function ignoreContact($contact_id) { $ignored = !Model\Contact::isIgnoredByUser($contact_id, local_user()); Model\Contact::setIgnoredForUser($contact_id, local_user(), $ignored); } private static function archiveContact($contact_id, $orig_record) { $archived = (($orig_record['archive']) ? 0 : 1); $r = DBA::update('contact', ['archive' => $archived], ['id' => $contact_id, 'uid' => local_user()]); return DBA::isResult($r); } private static function dropContact($orig_record) { $owner = Model\User::getOwnerDataById(local_user()); if (!DBA::isResult($owner)) { return; } Model\Contact::terminateFriendship($owner, $orig_record, true); Model\Contact::remove($orig_record['id']); } public static function content($update = 0) { $a = self::getApp(); $sort_type = 0; $o = ''; Nav::setSelected('contact'); if (!local_user()) { notice(L10n::t('Permission denied.') . EOL); return Login::form(); } if ($a->argc == 3) { $contact_id = intval($a->argv[1]); if (!$contact_id) { return; } $cmd = $a->argv[2]; $orig_record = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => [0, local_user()], 'self' => false]); if (!DBA::isResult($orig_record)) { notice(L10n::t('Could not access contact record.') . EOL); $a->redirect('contact'); return; // NOTREACHED } if ($cmd === 'update' && ($orig_record['uid'] != 0)) { self::updateContactFromPoll($contact_id); $a->redirect('contact/' . $contact_id); // NOTREACHED } if ($cmd === 'updateprofile' && ($orig_record['uid'] != 0)) { self::updateContactFromProbe($contact_id); $a->redirect('crepair/' . $contact_id); // NOTREACHED } if ($cmd === 'block') { self::blockContact($contact_id); $blocked = Model\Contact::isBlockedByUser($contact_id, local_user()); info(($blocked ? L10n::t('Contact has been blocked') : L10n::t('Contact has been unblocked')) . EOL); $a->redirect('contact/' . $contact_id); return; // NOTREACHED } if ($cmd === 'ignore') { self::ignoreContact($contact_id); $ignored = Model\Contact::isIgnoredByUser($contact_id, local_user()); info(($ignored ? L10n::t('Contact has been ignored') : L10n::t('Contact has been unignored')) . EOL); $a->redirect('contact/' . $contact_id); return; // NOTREACHED } if ($cmd === 'archive' && ($orig_record['uid'] != 0)) { $r = self::archiveContact($contact_id, $orig_record); if ($r) { $archived = (($orig_record['archive']) ? 0 : 1); info((($archived) ? L10n::t('Contact has been archived') : L10n::t('Contact has been unarchived')) . EOL); } $a->redirect('contact/' . $contact_id); return; // NOTREACHED } if ($cmd === 'drop' && ($orig_record['uid'] != 0)) { // Check if we should do HTML-based delete confirmation if (!empty($_REQUEST['confirm'])) { //